home *** CD-ROM | disk | FTP | other *** search
/ Aminet 35 / Aminet 35 (2000)(Schatztruhe)[!][Feb 2000].iso / Aminet / game / shoot / ADescentSrc.lha / descent / main / game.c < prev    next >
C/C++ Source or Header  |  1998-09-26  |  123KB  |  4,234 lines

  1. /*
  2. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  3. SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
  4. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  5. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  6. IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  7. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  8. FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  9. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
  10. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
  11. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
  12. */
  13. /*
  14.  * $Source: /usr/CVS/descent/main/game.c,v $
  15.  * $Revision: 1.15 $
  16.  * $Author: nobody $
  17.  * $Date: 1998/09/26 15:09:28 $
  18.  *
  19.  * Game loop for Inferno
  20.  *
  21.  * $Log: game.c,v $
  22.  * Revision 1.15  1998/09/26 15:09:28  nobody
  23.  * Added Warp3D support
  24.  *
  25.  * Revision 1.14  1998/08/08 15:43:33  nobody
  26.  * Activated the Editior
  27.  *
  28.  * Revision 1.13  1998/04/24 14:27:21  tfrieden
  29.  * Bugfixes
  30.  *
  31.  * Revision 1.12  1998/04/09 17:04:54  hfrieden
  32.  * Added ViRGE option menu
  33.  *
  34.  * Revision 1.11  1998/04/09 16:17:30  tfrieden
  35.  * Bugfixes
  36.  *
  37.  * Revision 1.10  1998/04/05 01:56:45  tfrieden
  38.  * Changed some if/else due to problems with palette fading
  39.  *
  40.  * Revision 1.9  1998/03/30 18:34:57  hfrieden
  41.  * Pause mode change to not use message box
  42.  *
  43.  * Revision 1.8  1998/03/30 11:48:08  tfrieden
  44.  * removed fps/memory counter
  45.  *
  46.  * Revision 1.7  1998/03/25 22:07:10  tfrieden
  47.  * Made some changes to set_screenmode (Boy, I hate compiling this thing)
  48.  *
  49.  * Revision 1.6  1998/03/22 16:04:25  hfrieden
  50.  * Added additional ViRGE stuff for palette handling
  51.  *
  52.  * Revision 1.5  1998/03/22 15:24:34  tfrieden
  53.  * removed lots of warning messages
  54.  *
  55.  * Revision 1.4  1998/03/18 23:20:32  tfrieden
  56.  * Bugfixes
  57.  *
  58.  * Revision 1.3  1998/03/14 13:58:42  hfrieden
  59.  * Preliminary ViRGE support added
  60.  *
  61.  * Revision 1.2  1998/03/13 23:51:46  tfrieden
  62.  * various changes with sound, joystick, shareware, notwork
  63.  *
  64.  * Revision 1.1.1.1  1998/03/03 15:12:21  nobody
  65.  * reimport after crash from backup
  66.  *
  67.  * Revision 1.3  1998/02/28 00:36:58  tfrieden
  68.  * aga support
  69.  *
  70.  * Revision 1.2  1998/02/16 20:40:43  tfrieden
  71.  * fixed cockpit masking
  72.  *
  73.  * Revision 1.1.1.1  1998/02/13  20:20:40  hfrieden
  74.  * Initial Import
  75.  */
  76.  
  77. #pragma off (unreferenced)
  78. static char rcsid[] = "$Id: game.c,v 1.15 1998/09/26 15:09:28 nobody Exp $";
  79. #pragma on (unreferenced)
  80.  
  81. #include <stdio.h>
  82. #include <malloc.h>
  83. #include <stdlib.h>
  84. #include <string.h>
  85. #include <stdarg.h>
  86. #include <bsd/bsd.h>
  87.  
  88. #include "inferno.h"
  89. #include "game.h"
  90. #include "key.h"
  91. #include "object.h"
  92. #include "physics.h"
  93. #include "error.h"
  94. #include "joy.h"
  95. #include "mono.h"
  96. #include "iff.h"
  97. #include "pcx.h"
  98. #include "timer.h"
  99. #include "render.h"
  100. #include "laser.h"
  101. #include "screens.h"
  102. #include "textures.h"
  103. #include "slew.h"
  104. #include "gauges.h"
  105. #include "texmap.h"
  106. #include "3d.h"
  107. #include "effects.h"
  108. #include "effect2d.h"
  109. #include "menu.h"
  110. #include "gameseg.h"
  111. #include "wall.h"
  112. #include "ai.h"
  113. #include "hostage.h"
  114. #include "fuelcen.h"
  115. #include "switch.h"
  116. #include "digi.h"
  117. #include "gamesave.h"
  118. #include "scores.h"
  119. #include "ibitblt.h"
  120. #include "mem.h"
  121. #include "palette.h"
  122. #include "morph.h"
  123. #include "lighting.h"
  124. #include "newdemo.h"
  125. #include "titles.h"
  126. #include "collide.h"
  127. #include "weapon.h"
  128. #include "sounds.h"
  129. #include "args.h"
  130. #include "gameseq.h"
  131. #include "automap.h"
  132. #include "text.h"
  133. #include "powerup.h"
  134. #include "fireball.h"
  135. #include "controls.h"
  136. #include "newmenu.h"
  137. #include "network.h"
  138. #include "gamefont.h"
  139. #include "endlevel.h"
  140. #include "joydefs.h"
  141. #include "kconfig.h"
  142. #include "mouse.h"
  143. #include "coindev.h"
  144. #include "multi.h"
  145. #include "desc_id.h"
  146. #include "cntrlcen.h"
  147. #include "pcx.h"
  148. #include "state.h"
  149. #include "piggy.h"
  150. #include "multibot.h"
  151. #include "ai.h"
  152. #ifdef VIRGIN
  153. #include "VirgeTexture.h"
  154. #define gr_printf gr_direct_printf
  155. extern void do_virge_menu(void);
  156. #endif
  157. //#define TEST_TIMER    1       //if this is set, do checking on timer
  158.  
  159. #ifdef WARP3D
  160. #include "Warp3D.h"
  161. #define gr_printf gr_direct_printf
  162. extern void do_warp_menu(void);
  163. #endif
  164.  
  165. #define SHOW_EXIT_PATH  1
  166. #define FINAL_CHEATS 1
  167.  
  168. #ifdef ARCADE
  169. #include "arcade.h"
  170. #else
  171. #define Arcade_mode 0
  172. #endif
  173.  
  174. #include "victor.h"
  175.  
  176. #include "vfx.h"
  177.  
  178. #ifdef EDITOR
  179. #include "editor/editor.h"
  180. #endif
  181.  
  182. //#define _MARK_ON 1
  183. //#include <wsample.h>            //should come after inferno.h to get mark setting
  184. //Above file is missing in the release version of the source. -KRB
  185.  
  186. int Speedtest_on = 0;
  187. extern int UseShareware;
  188.  
  189. #ifndef NDEBUG
  190. int Mark_count = 0;                 // number of debugging marks set
  191. int Speedtest_start_time;
  192. int Speedtest_segnum;
  193. int Speedtest_sidenum;
  194. int Speedtest_frame_start;
  195. int Speedtest_count=0;              //  number of times to do the debug test.
  196. #endif
  197.  
  198. #ifdef DEBUG_PROFILE
  199. extern fix profile_full_time;
  200. #endif
  201.  
  202.  
  203. fix minrate = 1000*F1_0;
  204. fix maxrate = 0;
  205. static fix last_timer_value=0;
  206.  
  207. #if defined(TIMER_TEST) && !defined(NDEBUG)
  208. fix _timer_value,actual_last_timer_value,_last_frametime;
  209. int stop_count,start_count;
  210. int time_stopped,time_started;
  211. #endif
  212.  
  213. ubyte * Game_cockpit_copy_code = NULL;
  214. ubyte Game_cockpit_double = 0;
  215.  
  216. ubyte new_cheats[]= {KEY_B^0xaa, KEY_B^0xaa, KEY_B^0xaa, KEY_F^0xaa, KEY_A^0xaa,
  217.                             KEY_U^0xaa, KEY_I^0xaa, KEY_R^0xaa, KEY_L^0xaa, KEY_H^0xaa,
  218.                             KEY_G^0xaa, KEY_G^0xaa, KEY_U^0xaa, KEY_A^0xaa, KEY_I^0xaa,
  219.                             KEY_G^0xaa, KEY_R^0xaa, KEY_I^0xaa, KEY_S^0xaa, KEY_M^0xaa,
  220.                             KEY_I^0xaa, KEY_E^0xaa, KEY_N^0xaa, KEY_H^0xaa, KEY_S^0xaa,
  221.                             KEY_N^0xaa, KEY_D^0xaa, KEY_X^0xaa, KEY_X^0xaa, KEY_A^0xaa };
  222.  
  223. ubyte           VR_use_paging       = 0;
  224. ubyte           VR_current_page = 0;
  225. ubyte           VR_switch_eyes      = 0;
  226. fix         VR_eye_width        = F1_0;
  227. int         VR_eye_offset       = 0;
  228. int         VR_eye_offset_changed   = 0;
  229. int         VR_screen_mode      = 0;
  230. int         VR_render_width = 0;
  231. int         VR_render_height    = 0;
  232. int         VR_render_mode      = VR_NONE;
  233. int         VR_compatible_menus = 0;
  234. int         VR_low_res          = 3;                // Default to low res
  235. int             VR_show_hud = 1;
  236. int         VR_sensitivity     = 1;     // 0 - 2
  237. grs_canvas  *VR_offscreen_buffer    = NULL;     // The offscreen data buffer
  238. grs_canvas  VR_render_buffer[2];                    //  Two offscreen buffers for left/right eyes.
  239. grs_canvas  VR_render_sub_buffer[2];            //  Two sub buffers for left/right eyes.
  240. grs_canvas  VR_screen_pages[2];                 //  Two pages of VRAM if paging is available
  241. grs_canvas  VR_editor_canvas;                       //  The canvas that the editor writes to.
  242.  
  243. int Debug_pause=0;              //John's debugging pause system
  244.  
  245. #if !defined(VIRGIN) && !defined(WARP3D)
  246. int Cockpit_mode=CM_FULL_COCKPIT;       //set game.h for values
  247. #else
  248. int Cockpit_mode=CM_FULL_SCREEN;
  249. #endif
  250. int old_cockpit_mode=-1;
  251. int force_cockpit_redraw=0;
  252.  
  253. int framerate_on=0;
  254.  
  255. int PaletteRedAdd, PaletteGreenAdd, PaletteBlueAdd;
  256.  
  257. //  Toggle_var points at a variable which gets !ed on ctrl-alt-T press.
  258. int Dummy_var;
  259. int *Toggle_var = &Dummy_var;
  260.  
  261. #ifdef EDITOR
  262. //flag for whether initial fade-in has been done
  263. char faded_in;
  264. #endif
  265.  
  266. #ifndef NDEBUG                          //these only exist if debugging
  267.  
  268. int Game_double_buffer = 1;     //double buffer by default
  269. fix fixed_frametime=0;          //if non-zero, set frametime to this
  270.  
  271. #endif
  272.  
  273. int Game_suspended=0;           //if non-zero, nothing moves but player
  274.  
  275. int Game_vfx_flag = 0;
  276. int Game_victor_flag = 0;
  277. int Game_vio_flag = 0;
  278. int Game_3dmax_flag = 0;
  279.  
  280.  
  281. #define VR_SEPARATION F1_0*7/10
  282. #define VR_PIXEL_SHIFT -6
  283. #define VR_DEFAULT_OFFSET_RATIO F1_0
  284. #define VR_MIN_SEPARATION F1_0/20
  285. #define VR_MAX_SEPARATION F1_0*2
  286. #define VR_DEFAULT_OFFSET_RATIO F1_0
  287. #define VR_MIN_OFFSET_RATIO F1_0/5
  288. #define VR_MAX_OFFSET_RATIO F1_0*2
  289.  
  290.             // basically, if pixel-shift equals -6, this adjustment factor
  291.             //    equals 7/6 (fixed-point);
  292. #define VR_ADJUST_OFFSET_RATIO (F1_0*(VR_PIXEL_SHIFT-1)/VR_PIXEL_SHIFT)
  293.  
  294. int simuleyes_offset_ratio = VR_DEFAULT_OFFSET_RATIO;
  295. int simuleyes_adjusted_offset_ratio;
  296. int simuleyes_right_eye_view;
  297. int Game_simuleyes_flag = 0;
  298.  
  299. int svr_black = 0x00;
  300. int svr_white = 0xFF;
  301.  
  302. void vr_reset_display();
  303.  
  304. fix     RealFrameTime;
  305. fix Auto_fire_fusion_cannon_time = 0;
  306. fix Fusion_charge = 0;
  307. fix Fusion_next_sound_time = 0;
  308.  
  309. int Debug_spew = 1;
  310. int Game_turbo_mode = 0;
  311.  
  312. int Game_mode = GM_GAME_OVER;
  313.  
  314. int Global_laser_firing_count = 0;
  315. int Global_missile_firing_count = 0;
  316.  
  317. grs_bitmap background_bitmap;
  318.  
  319. int Game_aborted;
  320.  
  321. extern void newdemo_strip_frames(char *, int);
  322.  
  323. #define BACKGROUND_NAME "statback.pcx"
  324.  
  325. void game_init_render_sub_buffers( int x, int y, int w, int h );
  326. void draw_centered_text( int y, char * s );
  327.  
  328.  
  329.  
  330. //  ==============================================================================================
  331.  
  332. #ifndef NDEBUG
  333. void speedtest_init(void)
  334. {
  335.     Speedtest_start_time = timer_get_fixed_seconds();
  336.     Speedtest_on = 1;
  337.     Speedtest_segnum = 0;
  338.     Speedtest_sidenum = 0;
  339.     Speedtest_frame_start = FrameCount;
  340.  
  341.     printf("Starting speedtest.  Will be %i frames.  Each . = 10 frames.\n", Highest_segment_index+1);
  342. }
  343.  
  344. void speedtest_frame(void)
  345. {
  346.     vms_vector  view_dir, center_point;
  347.  
  348.     Speedtest_sidenum=Speedtest_segnum % MAX_SIDES_PER_SEGMENT;
  349.  
  350.     compute_segment_center(&Viewer->pos, &Segments[Speedtest_segnum]);
  351.     Viewer->pos.x += 0x10;      Viewer->pos.y -= 0x10;      Viewer->pos.z += 0x17;
  352.  
  353.     obj_relink(Viewer-Objects, Speedtest_segnum);
  354.     compute_center_point_on_side(¢er_point, &Segments[Speedtest_segnum], Speedtest_sidenum);
  355.     vm_vec_normalized_dir_quick(&view_dir, ¢er_point, &Viewer->pos);
  356.     vm_vector_2_matrix(&Viewer->orient, &view_dir, NULL, NULL);
  357.  
  358.     if (((FrameCount - Speedtest_frame_start) % 10) == 0)
  359.         mprintf((0, "."));
  360.  
  361.     Speedtest_segnum++;
  362.  
  363.     if (Speedtest_segnum > Highest_segment_index) {
  364.         printf("\nSpeedtest done:  %i frames, %7.3f seconds, %7.3f frames/second.\n",
  365.             FrameCount-Speedtest_frame_start,
  366.             f2fl(timer_get_fixed_seconds() - Speedtest_start_time),
  367.             (float) (FrameCount-Speedtest_frame_start) / f2fl(timer_get_fixed_seconds() - Speedtest_start_time));
  368.         Speedtest_count--;
  369.         if (Speedtest_count == 0)
  370.             Speedtest_on = 0;
  371.         else
  372.             speedtest_init();
  373.     }               
  374.  
  375. }
  376.  
  377. #endif
  378.  
  379. //this is called once per game
  380. void init_game()
  381. {
  382.     ubyte pal[256*3];
  383.     int pcx_error;
  384.  
  385.     atexit(close_game);             //for cleanup
  386.  
  387.     init_objects();
  388.  
  389.     hostage_init();
  390.  
  391.     init_special_effects();
  392.  
  393.     init_ai_system();
  394.  
  395.     init_gauge_canvases();
  396.  
  397.     init_exploding_walls();
  398.  
  399.     background_bitmap.bm_data=NULL;
  400.     pcx_error = pcx_read_bitmap(BACKGROUND_NAME,&background_bitmap,BM_LINEAR,pal);
  401.     if (pcx_error != PCX_ERROR_NONE)
  402.         Error("File %s - PCX error: %s",BACKGROUND_NAME,pcx_errormsg(pcx_error));
  403.     gr_remap_bitmap_good( &background_bitmap, pal, -1, -1 );
  404.  
  405.     Clear_window = 2;       //  do portal only window clear.
  406. }
  407.  
  408.  
  409. void reset_palette_add()
  410. {
  411.     PaletteRedAdd       = 0;
  412.     PaletteGreenAdd = 0;
  413.     PaletteBlueAdd      = 0;
  414.     //gr_palette_step_up( PaletteRedAdd, PaletteGreenAdd, PaletteBlueAdd );
  415. }
  416.  
  417.  
  418. game_show_warning(char *s)
  419. {
  420.  
  421.     if (!((Game_mode & GM_MULTI) && (Function_mode == FMODE_GAME)))
  422.         stop_time();
  423.  
  424.     nm_messagebox( TXT_WARNING, 1, TXT_OK, s );
  425.  
  426.     if (!((Game_mode & GM_MULTI) && (Function_mode == FMODE_GAME)))
  427.         start_time();
  428. }
  429.  
  430.  
  431. //these should be in gr.h 
  432. #define cv_w  cv_bitmap.bm_w
  433. #define cv_h  cv_bitmap.bm_h
  434.  
  435. #define LETTERBOX_HEIGHT 140
  436.  
  437. int Game_window_w = 0;
  438. int Game_window_h = 0;
  439. int max_window_h = 0;
  440.  
  441. int last_drawn_cockpit[2] = { -1, -1 };
  442.  
  443. extern int Rear_view;
  444.  
  445. // This actually renders the new cockpit onto the screen.
  446. void update_cockpits(int force_redraw)
  447. {
  448.     int x, y, w, h;
  449.  
  450.     if (Cockpit_mode != last_drawn_cockpit[VR_current_page] || force_redraw )
  451.         last_drawn_cockpit[VR_current_page] = Cockpit_mode;
  452.     else
  453.         return;
  454.  
  455.     //Redraw the on-screen cockpit bitmaps
  456.     if (VR_render_mode != VR_NONE ) return;
  457.  
  458.     switch( Cockpit_mode )  {
  459.     case CM_FULL_COCKPIT:
  460.     case CM_REAR_VIEW:
  461.         gr_set_current_canvas(&VR_screen_pages[VR_current_page]);
  462.         PIGGY_PAGE_IN(cockpit_bitmap[Cockpit_mode]);
  463.         gr_ubitmapm(0,0, &GameBitmaps[cockpit_bitmap[Cockpit_mode].index]); 
  464.         break;
  465.     case CM_FULL_SCREEN:
  466.         break;
  467.     case CM_STATUS_BAR:
  468.         gr_set_current_canvas(&VR_screen_pages[VR_current_page]);
  469.         PIGGY_PAGE_IN(cockpit_bitmap[Cockpit_mode]);
  470.         gr_ubitmapm(0,max_window_h,&GameBitmaps[cockpit_bitmap[Cockpit_mode].index]);
  471.         w = Game_window_w;
  472.         h = Game_window_h;
  473.         x = (VR_render_width - w)/2;
  474.         y = (max_window_h - h)/2;
  475.         fill_background(x,y,w,h,x,y);
  476.         break;
  477.     case CM_LETTERBOX:
  478.         gr_set_current_canvas(&VR_screen_pages[VR_current_page]);
  479.         gr_clear_canvas( BM_XRGB(0,0,0) );
  480.         break;
  481.     }
  482.  
  483.     gr_set_current_canvas(&VR_screen_pages[VR_current_page]);
  484.     
  485.     if (Cockpit_mode==CM_FULL_COCKPIT || Cockpit_mode==CM_STATUS_BAR)
  486.         init_gauges();
  487.  
  488. }
  489.  
  490. //initialize the various canvases on the game screen
  491. //called every time the screen mode or cockpit changes
  492. void init_cockpit()
  493. {
  494.     int minx, maxx, miny, maxy;
  495.  
  496.     //Initialize the on-screen canvases
  497. #if !defined(VIRGIN) && !defined(WARP3D)
  498.     if ( VR_render_mode != VR_NONE )
  499.         Cockpit_mode = CM_FULL_SCREEN;
  500.  
  501.     if ( VR_screen_mode != SM_320x200C )    {       // This really should be 'if VR_screen_mode isn't linear'
  502.         // We can only use cockpit or rearview mode in mode 13h
  503.         //if ( (Cockpit_mode==CM_FULL_COCKPIT) || (Cockpit_mode==CM_REAR_VIEW) )    {
  504.         //  if (Game_window_h > max_window_h)           //too big for scalable
  505.         //      Cockpit_mode = CM_FULL_SCREEN;
  506.         //  else
  507.         //      Cockpit_mode = CM_STATUS_BAR;
  508.         //}
  509.         //if ( (grd_curscreen->sc_w > 320) || (VR_use_paging) )
  510.         //      Cockpit_mode = CM_FULL_SCREEN;
  511.         Cockpit_mode = CM_FULL_SCREEN;
  512.     }
  513.  
  514.     if ( Screen_mode == SCREEN_EDITOR )
  515.         Cockpit_mode = CM_FULL_SCREEN;
  516. #else
  517.     Cockpit_mode = CM_FULL_SCREEN;
  518. #endif
  519.  
  520.     gr_set_curfont( GAME_FONT );
  521.  
  522.     if (Game_cockpit_copy_code)
  523.         free(Game_cockpit_copy_code);
  524.     Game_cockpit_copy_code  = NULL;
  525.  
  526.     switch( Cockpit_mode )  {
  527.     case CM_FULL_COCKPIT:
  528.     case CM_REAR_VIEW:      {
  529.         grs_bitmap *bm = &GameBitmaps[cockpit_bitmap[Cockpit_mode].index];
  530.  
  531.         PIGGY_PAGE_IN(cockpit_bitmap[Cockpit_mode]);
  532.         gr_set_current_canvas(VR_offscreen_buffer);
  533.         gr_bitmap( 0, 0, bm );
  534.         bm = &VR_offscreen_buffer->cv_bitmap;
  535.         bm->bm_flags = BM_FLAG_TRANSPARENT;
  536.         gr_ibitblt_find_hole_size ( bm, &minx, &miny, &maxx, &maxy );
  537.         gr_ibitblt_create_mask( bm, minx, miny, maxx-minx+1, maxy-miny+1, VR_offscreen_buffer->cv_bitmap.bm_rowsize );
  538.         bm->bm_flags = 0;       // Clear all flags for offscreen canvas
  539.         game_init_render_sub_buffers( 0, 0, maxx-minx+1, maxy-miny+1 );
  540.         break;
  541.         }
  542.     case CM_FULL_SCREEN:
  543.         game_init_render_sub_buffers( 0, 0, VR_render_width, VR_render_height );
  544.         break;
  545.  
  546.     case CM_STATUS_BAR: {
  547.         int x,y;
  548.  
  549.         if (Game_window_h > max_window_h) {
  550.             Game_window_w = VR_render_width;
  551.             Game_window_h = max_window_h;
  552.         }
  553.  
  554.         x = (VR_render_width - Game_window_w)/2;
  555.         y = (max_window_h - Game_window_h)/2;
  556.  
  557.         game_init_render_sub_buffers( x, y, Game_window_w, Game_window_h );
  558.         break;
  559.         }
  560.     case CM_LETTERBOX:  {
  561.         int x,y,w,h;
  562.             
  563.         x = 0; w = VR_render_width;
  564.         h = LETTERBOX_HEIGHT;
  565.         y = (VR_render_height-h)/2;
  566.             
  567.         game_init_render_sub_buffers( x, y, w, h );
  568.         break;
  569.         }
  570.     }
  571.     gr_set_current_canvas(NULL);
  572. }
  573.  
  574. //selects a given cockpit (or lack of one).  See types in game.h
  575. void select_cockpit(int mode)
  576. {
  577. #if !defined(VIRGIN) && !defined(WARP3D)
  578.     if (mode != Cockpit_mode) {     //new mode
  579.         Cockpit_mode=mode;
  580.         init_cockpit();
  581.     }
  582. #endif
  583. }
  584.  
  585. //force cockpit redraw next time. call this if you've trashed the screen
  586. void reset_cockpit()
  587. {
  588.     force_cockpit_redraw=1;
  589.     last_drawn_cockpit[0] = -1;
  590.     last_drawn_cockpit[1] = -1;
  591. }
  592.  
  593. void HUD_clear_messages();
  594.  
  595. toggle_cockpit()
  596. {
  597.     int new_mode;
  598.  
  599.     switch (Cockpit_mode) {
  600.  
  601.         case CM_FULL_COCKPIT:
  602.             if (Game_window_h > max_window_h)           //too big for scalable
  603.                 new_mode = CM_FULL_SCREEN;
  604.             else
  605.                 new_mode = CM_STATUS_BAR;
  606.             break;
  607.  
  608.         case CM_STATUS_BAR:
  609.         case CM_FULL_SCREEN:
  610.             if (Rear_view)
  611.                 return;
  612.             new_mode = CM_FULL_COCKPIT;
  613.             break;
  614.  
  615.         case CM_REAR_VIEW:
  616.         case CM_LETTERBOX:
  617.             return;         //do nothing
  618.             break;
  619.  
  620.     }
  621.  
  622.     select_cockpit(new_mode);
  623.     HUD_clear_messages();
  624. }
  625.  
  626. #define WINDOW_W_DELTA 24   //20
  627. #define WINDOW_H_DELTA 12   //10
  628.  
  629. #define WINDOW_MIN_W        160
  630.  
  631. grow_window()
  632. {
  633.     if (Cockpit_mode == CM_FULL_COCKPIT) {
  634.         Game_window_h = max_window_h;
  635.         Game_window_w = VR_render_width;
  636.         toggle_cockpit();
  637.         grow_window();
  638.         HUD_init_message("Press F3 to return to Cockpit mode");
  639.         return;
  640.     }
  641.  
  642.     if (Cockpit_mode != CM_STATUS_BAR)
  643.         return;
  644.  
  645.     if (Game_window_h >= max_window_h) {
  646.         Game_window_w = VR_render_width;
  647.         Game_window_h = VR_render_height;
  648.         select_cockpit(CM_FULL_SCREEN);
  649.     } else {
  650.         int x,y;
  651.  
  652.         Game_window_w += WINDOW_W_DELTA;
  653.         Game_window_h += WINDOW_H_DELTA;
  654.  
  655.         if (Game_window_h > max_window_h)
  656.             Game_window_h = max_window_h;
  657.  
  658.         if (Game_window_w > VR_render_width)
  659.             Game_window_w = VR_render_width;
  660.  
  661.         if (Game_window_h > VR_render_height)
  662.             Game_window_h = VR_render_height;
  663.  
  664.         x = (VR_render_width - Game_window_w)/2;
  665.         y = (max_window_h - Game_window_h)/2;
  666.  
  667.         game_init_render_sub_buffers( x, y, Game_window_w, Game_window_h );
  668.     }
  669.  
  670.     HUD_clear_messages();   //  @mk, 11/11/94
  671. }
  672.  
  673. grs_bitmap background_bitmap;
  674.  
  675. copy_background_rect(int left,int top,int right,int bot)
  676. {
  677.     grs_bitmap *bm = &background_bitmap;
  678.     int x,y;
  679.     int tile_left,tile_right,tile_top,tile_bot;
  680.     int ofs_x,ofs_y;
  681.     int dest_x,dest_y;
  682.  
  683.     tile_left = left / bm->bm_w;
  684.     tile_right = right / bm->bm_w;
  685.     tile_top = top / bm->bm_h;
  686.     tile_bot = bot / bm->bm_h;
  687.  
  688.     ofs_y = top % bm->bm_h;
  689.     dest_y = top;
  690.  
  691.     for (y=tile_top;y<=tile_bot;y++) {
  692.         int w,h;
  693.  
  694.         ofs_x = left % bm->bm_w;
  695.         dest_x = left;
  696.  
  697.         //h = (bot < dest_y+bm->bm_h)?(bot-dest_y+1):(bm->bm_h-ofs_y);
  698.         h = min(bot-dest_y+1,bm->bm_h-ofs_y);
  699.  
  700.         for (x=tile_left;x<=tile_right;x++) {
  701.  
  702.             //w = (right < dest_x+bm->bm_w)?(right-dest_x+1):(bm->bm_w-ofs_x);
  703.             w = min(right-dest_x+1,bm->bm_w-ofs_x);
  704.         
  705.             gr_bm_ubitblt(w,h,dest_x,dest_y,ofs_x,ofs_y,
  706.                     &background_bitmap,&grd_curcanv->cv_bitmap);
  707.  
  708.             ofs_x = 0;
  709.             dest_x += w;
  710.         }
  711.  
  712.         ofs_y = 0;
  713.         dest_y += h;
  714.     }
  715.  
  716.  
  717. }
  718.  
  719. fill_background(int x,int y,int w,int h,int dx,int dy)
  720. {
  721.     gr_set_current_canvas(&VR_screen_pages[VR_current_page]);
  722.     copy_background_rect(x-dx,y-dy,x-1,y+h+dy-1);
  723.     copy_background_rect(x+w,y-dy,x+w+dx-1,y+h+dy-1);
  724.     copy_background_rect(x,y-dy,x+w-1,y-1);
  725.     copy_background_rect(x,y+h,x+w-1,y+h+dy-1);
  726. }
  727.  
  728. shrink_window()
  729. {
  730.     if (Cockpit_mode == CM_FULL_COCKPIT) {
  731.         Game_window_h = max_window_h;
  732.         Game_window_w = VR_render_width;
  733.         toggle_cockpit();
  734. //      shrink_window();
  735. //      shrink_window();
  736.         HUD_init_message("Press F3 to return to Cockpit mode");
  737.         return;
  738.     }
  739.  
  740.     if (Cockpit_mode == CM_FULL_SCREEN )    {
  741.         Game_window_h = max_window_h;
  742.         select_cockpit(CM_STATUS_BAR);
  743.         return;
  744.     }
  745.  
  746.     if (Cockpit_mode != CM_STATUS_BAR)
  747.         return;
  748.  
  749.     if (Game_window_w > WINDOW_MIN_W) {
  750.         int x,y;
  751.  
  752.         Game_window_w -= WINDOW_W_DELTA;
  753.         Game_window_h -= WINDOW_H_DELTA;
  754.  
  755.         if ( Game_window_w < WINDOW_MIN_W )
  756.             Game_window_w = WINDOW_MIN_W;
  757.  
  758.         x = (VR_render_width - Game_window_w)/2;
  759.         y = (max_window_h - Game_window_h)/2;
  760.  
  761.         fill_background(x,y,Game_window_w,Game_window_h,WINDOW_W_DELTA/2,WINDOW_H_DELTA/2);
  762.  
  763.         game_init_render_sub_buffers( x, y, Game_window_w, Game_window_h );
  764.     }
  765.  
  766.     HUD_clear_messages();
  767.  
  768. }
  769.  
  770. void game_init_render_sub_buffers( int x, int y, int w, int h )
  771. {
  772.     gr_init_sub_canvas( &VR_render_sub_buffer[0], &VR_render_buffer[0], x, y, w, h );
  773.     gr_init_sub_canvas( &VR_render_sub_buffer[1], &VR_render_buffer[1], x, y, w, h );
  774. }
  775.  
  776.  
  777. // Sets up the canvases we will be rendering to
  778. void game_init_render_buffers(int screen_mode, int render_w, int render_h, int use_paging, int render_method, int compatible_menus )
  779. {
  780.     if (!VR_offscreen_buffer)   {
  781.         VR_use_paging       = use_paging;
  782.         VR_switch_eyes      = 0;
  783.  
  784.         VR_eye_width        = VR_SEPARATION;    // 11/9/95
  785.         VR_eye_offset = VR_PIXEL_SHIFT;        // 11/9/95
  786.         simuleyes_adjusted_offset_ratio = fixdiv (VR_DEFAULT_OFFSET_RATIO *
  787.                     VR_PIXEL_SHIFT, VR_SEPARATION); // 11/10/95
  788.  
  789.         VR_screen_mode      = screen_mode;
  790.         VR_render_mode  = render_method;
  791.         VR_render_width = render_w;
  792.         VR_render_height    = render_h;
  793.         VR_compatible_menus = compatible_menus;
  794.     
  795.         Game_window_w       = render_w;
  796.         Game_window_h       = render_h;
  797.  
  798.         if ( (VR_render_mode==VR_AREA_DET) || (VR_render_mode==VR_INTERLACED ) )    {
  799.             if ( render_h*2 < 200 )
  800.                 VR_offscreen_buffer = gr_create_canvas( render_w, 200 );
  801.             else
  802.                 VR_offscreen_buffer = gr_create_canvas( render_w, render_h*2 );
  803.             gr_init_sub_canvas( &VR_render_buffer[0], VR_offscreen_buffer, 0, 0, render_w, render_h );
  804.             gr_init_sub_canvas( &VR_render_buffer[1], VR_offscreen_buffer, 0, render_h, render_w, render_h );
  805.         } else {
  806.             if ( render_h < 200 )
  807.                 VR_offscreen_buffer = gr_create_canvas( render_w, 200 );
  808.             else
  809.                 VR_offscreen_buffer = gr_create_canvas( render_w, render_h );
  810.             gr_init_sub_canvas( &VR_render_buffer[0], VR_offscreen_buffer, 0, 0, render_w, render_h );
  811.             gr_init_sub_canvas( &VR_render_buffer[1], VR_offscreen_buffer, 0, 0, render_w, render_h );
  812.         }
  813.         game_init_render_sub_buffers( 0, 0, render_w, render_h );
  814.     }
  815. }
  816.  
  817. //called to change the screen mode. Parameter sm is the new mode, one of
  818. //SMODE_GAME or SMODE_EDITOR. returns mode acutally set (could be other
  819. //mode if cannot init requested mode)
  820. int set_screen_mode(int sm)
  821. {
  822.     if ( (sm==SCREEN_MENU) && (Screen_mode==SCREEN_GAME) && VR_compatible_menus )   {
  823.         #ifdef DEBUG_SCREENMODE
  824.         printf("SM:GAME\n");
  825.         #endif
  826.         sm = SCREEN_GAME;
  827.     }
  828.  
  829. #ifdef EDITOR
  830.     if ( (sm==SCREEN_MENU) && (Screen_mode==SCREEN_EDITOR) )    {
  831.         gr_set_current_canvas( Canv_editor );
  832.         return 1;
  833.     }
  834. #endif
  835.  
  836.     if ( Screen_mode == sm ) {
  837.         gr_set_current_canvas( &VR_screen_pages[VR_current_page] );
  838. //      if ( VR_use_paging )    gr_show_canvas( &VR_screen_pages[VR_current_page] );
  839.         return 1;
  840.     }
  841.  
  842.     Screen_mode = sm;
  843.  
  844. #ifdef EDITOR
  845.     Canv_editor = NULL;
  846. #endif
  847.  
  848.     switch( Screen_mode )   {
  849.     case SCREEN_MENU:
  850.         #ifdef DEBUG_SCREENMODE
  851.         printf("SM:MENU\n");
  852.         #endif
  853.  
  854. //        if (grd_curscreen->sc_mode != SM_320x200C)  {
  855.         if (grd_curscreen->sc_w != 320 || grd_curscreen->sc_h != 200) {
  856.             if (gr_set_mode(SM_320x200C)) Error("Cannot set screen mode for game!");
  857.             gr_palette_load( gr_palette );
  858.         }
  859.  
  860.         gr_init_sub_canvas( &VR_screen_pages[0], &grd_curscreen->sc_canvas, 0, 0, grd_curscreen->sc_w, grd_curscreen->sc_h );
  861.         gr_init_sub_canvas( &VR_screen_pages[1], &grd_curscreen->sc_canvas, 0, 0, grd_curscreen->sc_w, grd_curscreen->sc_h );
  862.         break;
  863.     case SCREEN_GAME:
  864.         #ifdef DEBUG_SCREENMODE
  865.         printf("SM:GAME\n");
  866.         #endif
  867.         /*if (grd_curscreen->sc_mode != VR_screen_mode) {*/
  868.             #ifdef DEBUG_SCREENMODE
  869.             printf("Setting game mode\n");
  870.             #endif
  871.             if (gr_set_mode(VR_screen_mode))    {
  872.                 if ( VR_screen_mode != SM_640x480V )    
  873.                     Error("Cannot set screen mode for game!");
  874.                 else
  875.                     Error( "Cannot set screen mode for game!\nMake sure that you have a VESA driver loaded\nthat can display 640x480 in 256 colors.\n" );
  876.             }
  877. /*        }                                                  */
  878.         if ( VR_render_mode == VR_NONE )    {
  879.             if ( max_window_h == 0 )    {
  880.                 max_window_h = grd_curscreen->sc_h - GameBitmaps[cockpit_bitmap[CM_STATUS_BAR].index].bm_h;
  881.                 Game_window_h = max_window_h;
  882.             } else {
  883.                 max_window_h = grd_curscreen->sc_h - GameBitmaps[cockpit_bitmap[CM_STATUS_BAR].index].bm_h;
  884.             }
  885.         } else {
  886.             Cockpit_mode = CM_FULL_SCREEN;
  887.         }       
  888.         gr_init_sub_canvas( &VR_screen_pages[0], &grd_curscreen->sc_canvas, 0, 0, grd_curscreen->sc_w, grd_curscreen->sc_h );
  889.         if ( VR_use_paging )
  890.             gr_init_sub_canvas( &VR_screen_pages[1], &grd_curscreen->sc_canvas, 0, grd_curscreen->sc_h, grd_curscreen->sc_w, grd_curscreen->sc_h );
  891.         else
  892.             gr_init_sub_canvas( &VR_screen_pages[1], &grd_curscreen->sc_canvas, 0, 0, grd_curscreen->sc_w, grd_curscreen->sc_h );
  893.         break;
  894.     #ifdef EDITOR
  895.     case SCREEN_EDITOR:
  896.         if (grd_curscreen->sc_mode != SM_800x600V)  {
  897.             int gr_error;
  898.             if ((gr_error=gr_set_mode(SM_800x600V))!=0) { //force into game scrren
  899.                 Warning("Cannot init editor screen (error=%d)",gr_error);
  900.                 return 0;
  901.             }
  902.         }
  903.         gr_palette_load( gr_palette );
  904.  
  905.         gr_init_sub_canvas( &VR_editor_canvas, &grd_curscreen->sc_canvas, 0, 0, grd_curscreen->sc_w, grd_curscreen->sc_h );
  906.         Canv_editor = &VR_editor_canvas;
  907.         gr_init_sub_canvas( &VR_screen_pages[0], Canv_editor, 0, 0, Canv_editor->cv_w, Canv_editor->cv_h );
  908.         gr_init_sub_canvas( &VR_screen_pages[1], Canv_editor, 0, 0, Canv_editor->cv_w, Canv_editor->cv_h );
  909.         gr_set_current_canvas( Canv_editor );
  910.         init_editor_screen();   //setup other editor stuff
  911.         break;
  912.     #endif
  913.     default:
  914.         Error("Invalid screen mode %d",sm);
  915.     }
  916.  
  917.     VR_current_page = 0;
  918.  
  919.     init_cockpit();
  920.     
  921.     gr_set_current_canvas( &VR_screen_pages[VR_current_page] );
  922.     if ( VR_use_paging )    gr_show_canvas( &VR_screen_pages[VR_current_page] );
  923.  
  924.     return 1;
  925. }
  926.  
  927. #ifndef RELEASE
  928. fix frame_time_list[8] = {0,0,0,0,0,0,0,0};
  929. fix frame_time_total=0;
  930. int frame_time_cntr=0;
  931.  
  932. void ftoa(char *string, fix f)
  933. {
  934.     int decimal, fractional;
  935.     
  936.     decimal = f2i(f);
  937.     fractional = ((f & 0xffff)*100)/65536;
  938.     if (fractional < 0 )
  939.         fractional *= -1;
  940.     if (fractional > 99 ) fractional = 99;
  941.     sprintf( string, "%d.%02d", decimal, fractional );
  942. }
  943.  
  944. show_framerate()
  945. {
  946.     char temp[50];
  947.     fix rate;
  948.  
  949.     frame_time_total += RealFrameTime - frame_time_list[frame_time_cntr];
  950.     frame_time_list[frame_time_cntr] = RealFrameTime;
  951.     frame_time_cntr = (frame_time_cntr+1)%8;
  952.  
  953.     rate = fixdiv(f1_0*8,frame_time_total);
  954.  
  955.  
  956.     gr_set_curfont( GAME_FONT );    
  957.     gr_set_fontcolor(gr_getcolor(0,31,0),-1 );
  958.  
  959.     ftoa( temp, rate ); // Convert fixed to string
  960.     #if defined(VIRGIN) || defined(WARP3D)
  961.     gr_direct_printf(grd_curcanv->cv_w-50, grd_curcanv->cv_h-50, "FPS: %s", temp);
  962.     #else
  963.     gr_printf(grd_curcanv->cv_w-50,grd_curcanv->cv_h-20,"FPS: %s ", temp );
  964.     #endif
  965. }
  966. #endif
  967.  
  968. static timer_paused=0;      
  969.  
  970. void stop_time()
  971. {
  972.     if (timer_paused==0) {
  973.         fix time;
  974.         time = timer_get_fixed_seconds();
  975.         last_timer_value = time - last_timer_value;
  976.         if (last_timer_value < 0) {
  977.             #if defined(TIMER_TEST) && !defined(NDEBUG)
  978.             Int3();     //get Matt!!!!
  979.             #endif
  980.             last_timer_value = 0;
  981.         }
  982.         #if defined(TIMER_TEST) && !defined(NDEBUG)
  983.         time_stopped = time;
  984.         #endif
  985.     }
  986.     timer_paused++;
  987.  
  988.     #if defined(TIMER_TEST) && !defined(NDEBUG)
  989.     stop_count++;
  990.     #endif
  991. }
  992.  
  993. void start_time()
  994. {
  995.     timer_paused--;
  996.     Assert(timer_paused >= 0);
  997.     if (timer_paused==0) {
  998.         fix time;
  999.         time = timer_get_fixed_seconds();
  1000.         #if defined(TIMER_TEST) && !defined(NDEBUG)
  1001.         if (last_timer_value < 0)
  1002.             Int3();     //get Matt!!!!
  1003.         }
  1004.         #endif
  1005.         last_timer_value = time - last_timer_value;
  1006.         #if defined(TIMER_TEST) && !defined(NDEBUG)
  1007.         time_started = time;
  1008.         #endif
  1009.     }
  1010.  
  1011.     #if defined(TIMER_TEST) && !defined(NDEBUG)
  1012.     start_count++;
  1013.     #endif
  1014. }
  1015.  
  1016. void game_flush_inputs()
  1017. {
  1018.     int dx,dy;
  1019.     key_flush();
  1020.     joy_flush();            
  1021.     mouse_flush();
  1022.     mouse_get_delta( &dx, &dy );    // Read mouse
  1023.     memset(&Controls,0,sizeof(control_info));
  1024. }
  1025.  
  1026. void reset_time()
  1027. {
  1028.     last_timer_value = timer_get_fixed_seconds();
  1029.  
  1030. }
  1031.  
  1032. void calc_frame_time()
  1033. {
  1034.     fix timer_value,last_frametime = FrameTime;
  1035.  
  1036.     #if defined(TIMER_TEST) && !defined(NDEBUG)
  1037.     _last_frametime = last_frametime;
  1038.     #endif
  1039.  
  1040.     timer_value = timer_get_fixed_seconds();
  1041.     FrameTime = timer_value - last_timer_value;
  1042.  
  1043.     #if defined(TIMER_TEST) && !defined(NDEBUG)
  1044.     _timer_value = timer_value;
  1045.     #endif
  1046.     
  1047.     #ifndef NDEBUG
  1048.     if (!(((FrameTime > 0) && (FrameTime <= F1_0)) || (Function_mode == FMODE_EDITOR) || (Newdemo_state == ND_STATE_PLAYBACK))) {
  1049.         mprintf((1,"Bad FrameTime - value = %x\n",FrameTime));
  1050.         if (FrameTime == 0)
  1051.             Int3(); //  Call Mike or Matt or John!  Your interrupts are probably trashed!
  1052. //      if ( !dpmi_virtual_memory )
  1053. //          Int3();     //Get MATT if hit this!
  1054.     }
  1055.     #endif
  1056.  
  1057.     #if defined(TIMER_TEST) && !defined(NDEBUG)
  1058.     actual_last_timer_value = last_timer_value;
  1059.     #endif
  1060.  
  1061.     if ( Game_turbo_mode )
  1062.         FrameTime *= 2;
  1063.  
  1064.     // Limit frametime to be between 5 and 150 fps.
  1065.     RealFrameTime = FrameTime;
  1066.     if ( FrameTime < F1_0/150 ) FrameTime = F1_0/150;
  1067.     if ( FrameTime > F1_0/5 ) FrameTime = F1_0/5;
  1068.  
  1069.     last_timer_value = timer_value;
  1070.  
  1071.     if (FrameTime < 0)                      //if bogus frametime...
  1072.         FrameTime = last_frametime;     //...then use time from last frame
  1073.  
  1074.     #ifndef NDEBUG
  1075.     if (fixed_frametime) FrameTime = fixed_frametime;
  1076.     #endif
  1077.  
  1078.     if (FrameTime < minrate) minrate = FrameTime;
  1079.     if (FrameTime > maxrate) maxrate = FrameTime;
  1080.  
  1081.  
  1082.     #ifndef NDEBUG
  1083.     // Pause here!!!
  1084.     if ( Debug_pause )      {
  1085.         int c;
  1086.         c = 0;
  1087.         while( c==0 )
  1088.             c = key_peekkey();
  1089.             
  1090.         if ( c == KEY_P )       {
  1091.             Debug_pause = 0;
  1092.             c = key_inkey();
  1093.         }
  1094.         last_timer_value = timer_get_fixed_seconds();
  1095.     }
  1096.     #endif
  1097.  
  1098.     #if Arcade_mode
  1099.         FrameTime /= 2;
  1100.     #endif
  1101.  
  1102.     #if defined(TIMER_TEST) && !defined(NDEBUG)
  1103.     stop_count = start_count = 0;
  1104.     #endif
  1105.  
  1106.     //  Set value to determine whether homing missile can see target.
  1107.     //  The lower frametime is, the more likely that it can see its target.
  1108.     if (FrameTime <= F1_0/16)
  1109.         Min_trackable_dot = 3*(F1_0 - MIN_TRACKABLE_DOT)/4 + MIN_TRACKABLE_DOT;
  1110.     else if (FrameTime < F1_0/4)
  1111.         Min_trackable_dot = fixmul(F1_0 - MIN_TRACKABLE_DOT, F1_0-4*FrameTime) + MIN_TRACKABLE_DOT;
  1112.     else
  1113.         Min_trackable_dot = MIN_TRACKABLE_DOT;
  1114.  
  1115. }
  1116.  
  1117. //--unused-- int Auto_flythrough=0;  //if set, start flythough automatically
  1118.  
  1119. void move_player_2_segment(segment *seg,int side)
  1120. {
  1121.     vms_vector vp;
  1122.  
  1123.     compute_segment_center(&ConsoleObject->pos,seg);
  1124.     compute_center_point_on_side(&vp,seg,side);
  1125.     vm_vec_sub2(&vp,&ConsoleObject->pos);
  1126.     vm_vector_2_matrix(&ConsoleObject->orient,&vp,NULL,NULL);
  1127.  
  1128.     obj_relink( ConsoleObject-Objects, SEG_PTR_2_NUM(seg) );
  1129.     
  1130. }
  1131.  
  1132. fix Show_view_text_timer = -1;
  1133.  
  1134. #ifndef NDEBUG
  1135.  
  1136. draw_window_label()
  1137. {
  1138.     if ( Show_view_text_timer > 0 )
  1139.     {
  1140.         char *viewer_name,*control_name;
  1141.  
  1142.         Show_view_text_timer -= FrameTime;
  1143.         gr_set_curfont( GAME_FONT );
  1144.  
  1145.         switch( Viewer->type )
  1146.         {
  1147.             case OBJ_FIREBALL:  viewer_name = "Fireball"; break;
  1148.             case OBJ_ROBOT:     viewer_name = "Robot"; break;
  1149.             case OBJ_HOSTAGE:       viewer_name = "Hostage"; break;
  1150.             case OBJ_PLAYER:        viewer_name = "Player"; break;
  1151.             case OBJ_WEAPON:        viewer_name = "Weapon"; break;
  1152.             case OBJ_CAMERA:        viewer_name = "Camera"; break;
  1153.             case OBJ_POWERUP:       viewer_name = "Powerup"; break;
  1154.             case OBJ_DEBRIS:        viewer_name = "Debris"; break;
  1155.             case OBJ_CNTRLCEN:  viewer_name = "Control Center"; break;
  1156.             default:                    viewer_name = "Unknown"; break;
  1157.         }
  1158.  
  1159.         switch ( Viewer->control_type) {
  1160.             case CT_NONE:           control_name = "Stopped"; break;
  1161.             case CT_AI:             control_name = "AI"; break;
  1162.             case CT_FLYING:     control_name = "Flying"; break;
  1163.             case CT_SLEW:           control_name = "Slew"; break;
  1164.             case CT_FLYTHROUGH: control_name = "Flythrough"; break;
  1165.             case CT_MORPH:          control_name = "Morphing"; break;
  1166.             default:                    control_name = "Unknown"; break;
  1167.         }
  1168.  
  1169.         gr_set_fontcolor( gr_getcolor(31, 0, 0), -1 );
  1170.         gr_printf( 0x8000, 45, "%s View - %s",viewer_name,control_name );
  1171.  
  1172.     }
  1173. }
  1174. #endif
  1175.  
  1176.  
  1177. void render_countdown_gauge()
  1178. {
  1179.     if (!Endlevel_sequence && Fuelcen_control_center_destroyed  && (Fuelcen_seconds_left>-1) && (Fuelcen_seconds_left<127)) {
  1180.         int y;
  1181.         gr_set_curfont( Gamefonts[4] );    //GAME_FONT );
  1182.     #ifdef VIRGIN
  1183.         gr_set_fontcolor(gr_getcolor(63,0,0), -1);
  1184.     #else
  1185.         gr_set_fontcolor(gr_getcolor(0,63,0), -1 );
  1186.     #endif
  1187.         y = 20;
  1188.         if (!((Cockpit_mode == CM_STATUS_BAR) && (Game_window_w >= 19)))
  1189.             y += 5;
  1190.  
  1191.         gr_printf(0x8000, y, "T-%d s", Fuelcen_seconds_left );
  1192.     }
  1193. }
  1194.  
  1195. #ifdef NETWORK
  1196. void game_draw_multi_message()
  1197. {
  1198.     char temp_string[MAX_MULTI_MESSAGE_LEN+25];
  1199.  
  1200.     if ( (Game_mode&GM_MULTI) && (multi_sending_message))   {
  1201.         gr_set_curfont( GAME_FONT );    //GAME_FONT );
  1202.         gr_set_fontcolor(gr_getcolor(0,63,0), -1 );
  1203.         sprintf( temp_string, "%s: %s_", TXT_MESSAGE, Network_message );
  1204.         draw_centered_text(grd_curcanv->cv_bitmap.bm_h/2-16, temp_string );
  1205.  
  1206.     }
  1207.  
  1208.     if ( (Game_mode&GM_MULTI) && (multi_defining_message))  {
  1209.         gr_set_curfont( GAME_FONT );    //GAME_FONT );
  1210.         gr_set_fontcolor(gr_getcolor(0,63,0), -1 );
  1211.         sprintf( temp_string, "%s #%d: %s_", TXT_MACRO, multi_defining_message, Network_message );
  1212.         draw_centered_text(grd_curcanv->cv_bitmap.bm_h/2-16, temp_string );
  1213.     }
  1214. }
  1215. #endif
  1216.  
  1217. // Returns the length of the first 'n' characters of a string.
  1218. int string_width( char * s, int n )
  1219. {
  1220.     int w,h,aw;
  1221.     char p;
  1222.     p = s[n];
  1223.     s[n] = 0;
  1224.     gr_get_string_size( s, &w, &h, &aw );
  1225.     s[n] = p;
  1226.     return w;
  1227. }
  1228.  
  1229. // Draw string 's' centered on a canvas... if wider than
  1230. // canvas, then wrap it.
  1231. void draw_centered_text( int y, char * s )
  1232. {
  1233.     int i, l;
  1234.     char p;
  1235.  
  1236.  
  1237.     l = strlen(s);
  1238.  
  1239.     if ( string_width( s, l ) < grd_curcanv->cv_bitmap.bm_w )   {
  1240.         gr_string( 0x8000, y, s );
  1241.         return;
  1242.     }
  1243.  
  1244.     for (i=0; i<l; i++ )    {
  1245.         if ( string_width(s,i) > (grd_curcanv->cv_bitmap.bm_w - 16) )   {
  1246.             p = s[i];
  1247.             s[i] = 0;
  1248.             gr_string( 0x8000, y, s );
  1249.             s[i] = p;
  1250.             gr_string( 0x8000, y+grd_curcanv->cv_font->ft_h+1, &s[i] );
  1251.             return;
  1252.         }
  1253.     }
  1254. }
  1255.  
  1256. extern fix Cruise_speed;
  1257.  
  1258. void game_draw_hud_stuff()
  1259. {
  1260.  
  1261.     #ifndef NDEBUG
  1262.     if (Debug_pause) {
  1263.         gr_set_curfont( HELP_FONT );
  1264.         gr_set_fontcolor( gr_getcolor(31, 31, 31), -1 ); // gr_getcolor(31,0,0));
  1265.         gr_ustring( 0x8000, 85/2, "Debug Pause - Press P to exit" );
  1266.     }
  1267.     #endif
  1268.  
  1269.     #ifdef CROSSHAIR
  1270.     if ( Viewer->type == OBJ_PLAYER )
  1271.         laser_do_crosshair(Viewer);
  1272.     #endif
  1273.     
  1274.     #ifndef NDEBUG
  1275.     draw_window_label();
  1276.     #endif
  1277.  
  1278.     #ifdef NETWORK
  1279.     game_draw_multi_message();
  1280.     #endif
  1281.  
  1282.     if ((Newdemo_state == ND_STATE_PLAYBACK) || (Newdemo_state == ND_STATE_RECORDING)) {
  1283.         char message[128];
  1284.         int h,w,aw;
  1285.  
  1286.         if (Newdemo_state == ND_STATE_PLAYBACK) {
  1287.             if (Newdemo_vcr_state != ND_STATE_PRINTSCREEN) {
  1288.                 sprintf(message, "%s (%d%%%% %s)", TXT_DEMO_PLAYBACK, newdemo_get_percent_done(), TXT_DONE);
  1289.             } else {
  1290.                 sprintf (message, "");
  1291.             }
  1292.         } else 
  1293.             sprintf (message, TXT_DEMO_RECORDING);
  1294.  
  1295.         gr_set_curfont( GAME_FONT );    //GAME_FONT );
  1296.         gr_set_fontcolor(gr_getcolor(27,0,0), -1 );
  1297.  
  1298.         gr_get_string_size(message, &w, &h, &aw );
  1299.         if (Cockpit_mode == CM_FULL_COCKPIT)
  1300.             h += 15;
  1301.         else if ( Cockpit_mode == CM_LETTERBOX )
  1302.             h += 7;
  1303.  
  1304.         if (Cockpit_mode != CM_REAR_VIEW)
  1305.             gr_printf((grd_curcanv->cv_bitmap.bm_w-w)/2, grd_curcanv->cv_bitmap.bm_h - h - 2, message );
  1306.     }
  1307.  
  1308.     render_countdown_gauge();
  1309.  
  1310.     if ( Player_num > -1 && Viewer->type==OBJ_PLAYER && Viewer->id==Player_num )    {
  1311.         int x = 3;
  1312.         int y = grd_curcanv->cv_bitmap.bm_h;
  1313.  
  1314.         gr_set_curfont( GAME_FONT );
  1315.         gr_set_fontcolor( gr_getcolor(0, 31, 0), -1 );
  1316.         if (Cruise_speed > 0)
  1317.             if (Cockpit_mode==CM_FULL_SCREEN) {
  1318.                 if (Game_mode & GM_MULTI)
  1319.                     y -= 64;
  1320.                 else
  1321.                     y -= 24;
  1322.             } else if (Cockpit_mode == CM_STATUS_BAR) {
  1323.                 if (Game_mode & GM_MULTI)
  1324.                     y -= 48;
  1325.                 else
  1326.                     y -= 24;
  1327.             } else {
  1328.                 y = 12;
  1329.                 x = 20;
  1330.             }
  1331.  
  1332.             gr_printf( x, y, "%s %2d%%", TXT_CRUISE, f2i(Cruise_speed) );
  1333.  
  1334.     }
  1335.  
  1336.     #ifdef ARCADE
  1337.     arcade_frame_info();
  1338.     #endif
  1339.  
  1340. #ifndef RELEASE
  1341.     if (framerate_on)
  1342.         show_framerate();
  1343. #endif
  1344.  
  1345.     if (UseShareware) {
  1346.         if ( (Newdemo_state == ND_STATE_PLAYBACK) )
  1347.             Game_mode = Newdemo_game_mode;
  1348.     }
  1349.  
  1350.     draw_hud();
  1351.  
  1352.     if (UseShareware) {
  1353.         if ( (Newdemo_state == ND_STATE_PLAYBACK) )
  1354.             Game_mode = GM_NORMAL;
  1355.     }
  1356.  
  1357.     if ( Player_is_dead )
  1358.         player_dead_message();
  1359. }
  1360.  
  1361. extern int gr_bitblt_dest_step_shift;
  1362. extern int gr_wait_for_retrace;
  1363. extern int gr_bitblt_double;
  1364.  
  1365. //render a frame for the game in stereo
  1366. game_render_frame_stereo_vfx()
  1367. {
  1368.     int dw,dh,sw,sh;
  1369.     fix save_aspect;
  1370.     grs_canvas RenderCanvas[2];
  1371.  
  1372.     save_aspect = grd_curscreen->sc_aspect;
  1373.  
  1374.     sw = dw = VR_render_buffer[0].cv_bitmap.bm_w;
  1375.     sh = dh = VR_render_buffer[0].cv_bitmap.bm_h;
  1376.  
  1377.     if (VR_low_res & 1) {
  1378.         sh /= 2;                
  1379.         grd_curscreen->sc_aspect *= 2;  //Muck with aspect ratio                            
  1380.     }
  1381.     if (VR_low_res & 2) {
  1382.         sw /= 2;                
  1383.         grd_curscreen->sc_aspect /= 2;  //Muck with aspect ratio                            
  1384.     }
  1385.  
  1386.     gr_init_sub_canvas( &RenderCanvas[0], &VR_render_buffer[0], 0, 0, sw, sh );
  1387.     gr_init_sub_canvas( &RenderCanvas[1], &VR_render_buffer[1], 0, 0, sw, sh );
  1388.  
  1389.     // Draw the left eye's view
  1390.     if (VR_switch_eyes) 
  1391.         gr_set_current_canvas(&RenderCanvas[1]);
  1392.     else
  1393.         gr_set_current_canvas(&RenderCanvas[0]);
  1394.     render_frame(-VR_eye_width);        // Left eye
  1395.     if ( VR_show_hud )
  1396.         game_draw_hud_stuff();
  1397.  
  1398.     // Draw the right eye's view
  1399.     if (VR_switch_eyes) 
  1400.         gr_set_current_canvas(&RenderCanvas[0]);
  1401.     else
  1402.         gr_set_current_canvas(&RenderCanvas[1]);
  1403.     render_frame(VR_eye_width);     // Right eye
  1404.  
  1405.     // Copy left eye, then right eye
  1406.     VR_current_page = !VR_current_page;
  1407.     gr_bitblt_dest_step_shift = 1;      // Skip every other scanline.
  1408.  
  1409.     if ( VR_low_res & 2 )       // Horizontal stretch
  1410.         gr_bitblt_double = 1;
  1411.  
  1412.     if ( VR_low_res & 1 )   {
  1413.         gr_bitblt_dest_step_shift = 2;          // Vertical stretch
  1414.         gr_bm_ubitblt( dw, sh, 0, VR_current_page, 0, 0, &RenderCanvas[0].cv_bitmap, &VR_screen_pages[0].cv_bitmap);
  1415.         gr_bm_ubitblt( dw, sh, 0, VR_current_page+2, 0, 0, &RenderCanvas[0].cv_bitmap, &VR_screen_pages[0].cv_bitmap);
  1416.         gr_bm_ubitblt( dw, sh, dw, VR_current_page, 0, 0, &RenderCanvas[1].cv_bitmap, &VR_screen_pages[0].cv_bitmap);
  1417.         gr_bm_ubitblt( dw, sh, dw, VR_current_page+2, 0, 0, &RenderCanvas[1].cv_bitmap, &VR_screen_pages[0].cv_bitmap);
  1418.     } else {
  1419.         gr_bm_ubitblt( dw, sh, 0, VR_current_page, 0, 0, &RenderCanvas[0].cv_bitmap, &VR_screen_pages[0].cv_bitmap);
  1420.         gr_bm_ubitblt( dw, sh, dw, VR_current_page, 0, 0, &RenderCanvas[1].cv_bitmap, &VR_screen_pages[0].cv_bitmap);
  1421.     }
  1422.  
  1423.     gr_bitblt_double = 0;
  1424.     gr_bitblt_dest_step_shift = 0;
  1425.  
  1426.     grd_curscreen->sc_aspect = save_aspect; //restore aspect
  1427. }
  1428.  
  1429.  
  1430.  
  1431. //render a frame for the game in stereo
  1432. game_render_frame_stereo_interlaced()
  1433. {
  1434.     int dw,dh,sw,sh;
  1435.     fix save_aspect;
  1436.     grs_canvas RenderCanvas[2];
  1437.  
  1438.     save_aspect = grd_curscreen->sc_aspect;
  1439.     grd_curscreen->sc_aspect *= 2;  //Muck with aspect ratio
  1440.  
  1441.     sw = dw = VR_render_buffer[0].cv_bitmap.bm_w;
  1442.     sh = dh = VR_render_buffer[0].cv_bitmap.bm_h;
  1443.  
  1444.     if (VR_low_res & 1) {
  1445.         sh /= 2;                
  1446.         grd_curscreen->sc_aspect *= 2;  //Muck with aspect ratio                            
  1447.     }
  1448.     if (VR_low_res & 2) {
  1449.         sw /= 2;                
  1450.         grd_curscreen->sc_aspect /= 2;  //Muck with aspect ratio                            
  1451.     }
  1452.  
  1453.     gr_init_sub_canvas( &RenderCanvas[0], &VR_render_buffer[0], 0, 0, sw, sh );
  1454.     gr_init_sub_canvas( &RenderCanvas[1], &VR_render_buffer[1], 0, 0, sw, sh );
  1455.  
  1456.     // Draw the left eye's view
  1457.     if (VR_switch_eyes) 
  1458.         gr_set_current_canvas(&RenderCanvas[1]);
  1459.     else
  1460.         gr_set_current_canvas(&RenderCanvas[0]);
  1461.  
  1462.     if (Rear_view)
  1463.         render_frame(VR_eye_width); // switch eye positions for rear view
  1464.     else
  1465.         render_frame(-VR_eye_width);        // Left eye
  1466.  
  1467.     if (VR_eye_offset > 0 ) {
  1468.         gr_setcolor( gr_getcolor(0,0,0) );
  1469.         gr_rect( grd_curcanv->cv_bitmap.bm_w-labs(VR_eye_offset)*2, 0, 
  1470.                grd_curcanv->cv_bitmap.bm_w-1, grd_curcanv->cv_bitmap.bm_h );
  1471.     } else if (VR_eye_offset < 0 ) {
  1472.         gr_setcolor( gr_getcolor(0,0,0) );
  1473.         gr_rect( 0, 0, labs(VR_eye_offset)*2-1, grd_curcanv->cv_bitmap.bm_h );
  1474.     }
  1475.  
  1476.     if ( VR_show_hud )  {
  1477.         grs_canvas tmp;
  1478.         if (VR_eye_offset < 0 ) {
  1479.             gr_init_sub_canvas( &tmp, grd_curcanv, labs(VR_eye_offset*2), 0, grd_curcanv->cv_bitmap.bm_w-(labs(VR_eye_offset)*2), grd_curcanv->cv_bitmap.bm_h );
  1480.         } else {
  1481.             gr_init_sub_canvas( &tmp, grd_curcanv, 0, 0, grd_curcanv->cv_bitmap.bm_w-(labs(VR_eye_offset)*2), grd_curcanv->cv_bitmap.bm_h );
  1482.         }
  1483.         gr_set_current_canvas( &tmp );
  1484.         game_draw_hud_stuff();
  1485.     }
  1486.  
  1487.  
  1488.     // Draw the right eye's view
  1489.     if (VR_switch_eyes) 
  1490.         gr_set_current_canvas(&RenderCanvas[0]);
  1491.     else
  1492.         gr_set_current_canvas(&RenderCanvas[1]);
  1493.  
  1494.     if (Rear_view)
  1495.         render_frame(-VR_eye_width);    // switch eye positions for rear view
  1496.     else
  1497.         render_frame(VR_eye_width);     // Right eye
  1498.  
  1499.     if (VR_eye_offset>0) {
  1500.         gr_setcolor( gr_getcolor(0,0,0) );
  1501.         gr_rect( 0, 0, labs(VR_eye_offset)*2-1, grd_curcanv->cv_bitmap.bm_h );
  1502.     } else if ( VR_eye_offset < 0 ) {
  1503.         gr_setcolor( gr_getcolor(0,0,0) );
  1504.         gr_rect( grd_curcanv->cv_bitmap.bm_w-labs(VR_eye_offset)*2, 0, 
  1505.                grd_curcanv->cv_bitmap.bm_w-1, grd_curcanv->cv_bitmap.bm_h );
  1506.     }
  1507.  
  1508.     if ( VR_show_hud )  {
  1509.         grs_canvas tmp;
  1510.         if (VR_eye_offset > 0 ) {
  1511.             gr_init_sub_canvas( &tmp, grd_curcanv, labs(VR_eye_offset*2), 0, grd_curcanv->cv_bitmap.bm_w-(labs(VR_eye_offset)*2), grd_curcanv->cv_bitmap.bm_h );
  1512.         } else {
  1513.             gr_init_sub_canvas( &tmp, grd_curcanv, 0, 0, grd_curcanv->cv_bitmap.bm_w-(labs(VR_eye_offset)*2), grd_curcanv->cv_bitmap.bm_h );
  1514.         }
  1515.         gr_set_current_canvas( &tmp );
  1516.         game_draw_hud_stuff();
  1517.     }
  1518.  
  1519.  
  1520.     // Draws white and black registration encoding lines
  1521.     // and Accounts for pixel-shift adjustment in upcoming bitblts
  1522.     if (Game_simuleyes_flag)    {
  1523.         int width, height, quarter, nibble;
  1524.         void *pixptr, *drawptr;
  1525.  
  1526.         width = RenderCanvas[0].cv_bitmap.bm_w;
  1527.         height = RenderCanvas[0].cv_bitmap.bm_h;
  1528.         pixptr = RenderCanvas[0].cv_bitmap.bm_data;
  1529.         quarter = width / 4;
  1530.         nibble = labs(VR_eye_offset); // pixel-shift amount
  1531.  
  1532.         // black out left-hand side of left page
  1533.  
  1534.         // draw registration code for left eye
  1535.         drawptr = (void*)((int)pixptr + width*(height-1) - VR_eye_offset);
  1536.         memset(drawptr, svr_white, quarter);
  1537.         drawptr = (void*)((int)drawptr + quarter);
  1538.         if (VR_eye_offset < 0) // stay within buffer limit
  1539.             memset(drawptr, svr_black, 3*quarter - nibble);
  1540.         else
  1541.             memset(drawptr, svr_black, 3*quarter);
  1542.  
  1543.         // black out right-hand side of right page
  1544.         pixptr = RenderCanvas[1].cv_bitmap.bm_data;
  1545.  
  1546.  
  1547.         // draw registration code for right eye
  1548.         drawptr = (void*)((int)pixptr + width*(height-1) + VR_eye_offset);
  1549.         memset(drawptr, svr_white, 3*quarter);
  1550.         drawptr = (void*)((int)drawptr + 3*quarter);
  1551.         if (VR_eye_offset > 0) // stay within buffer limit
  1552.             memset(drawptr, svr_black, quarter - nibble);
  1553.         else
  1554.             memset(drawptr, svr_black, quarter);
  1555.    }
  1556.  
  1557.         // Copy left eye, then right eye
  1558.     if (  VR_use_paging   )
  1559.         VR_current_page = !VR_current_page;
  1560.     else 
  1561.         VR_current_page = 0;
  1562.     gr_set_current_canvas( &VR_screen_pages[VR_current_page] );
  1563.  
  1564.     if ( VR_eye_offset_changed > 0 )    {
  1565.         VR_eye_offset_changed--;
  1566.         gr_clear_canvas(0);
  1567.     }
  1568.  
  1569.     if ( VR_low_res & 2 )       // Horizontal stretch
  1570.         gr_bitblt_double = 1;
  1571.  
  1572.     // Copy left eye, then right eye
  1573.     if ( VR_low_res & 1 )   {
  1574.         gr_bitblt_dest_step_shift = 2;  // Skip every 4 scanlines.
  1575.         if ( VR_eye_offset > 0 )    {
  1576.             int xoff = labs(VR_eye_offset);
  1577.             gr_bm_ubitblt( dw-xoff, dh/2, xoff, 0, 0, 0, &RenderCanvas[0].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap);
  1578.             gr_bm_ubitblt( dw-xoff, dh/2, 0, 1, xoff, 0, &RenderCanvas[1].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap);
  1579.             gr_bm_ubitblt( dw-xoff, dh/2, xoff, 2, 0, 0, &RenderCanvas[0].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap);
  1580.             gr_bm_ubitblt( dw-xoff, dh/2, 0, 3, xoff, 0, &RenderCanvas[1].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap);
  1581.         } else if ( VR_eye_offset < 0 ) {
  1582.             int xoff = labs(VR_eye_offset);
  1583.             gr_bm_ubitblt( dw-xoff, dh/2, 0, 0, xoff, 0, &RenderCanvas[0].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap);
  1584.             gr_bm_ubitblt( dw-xoff, dh/2, xoff, 1, 0, 0, &RenderCanvas[1].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap);
  1585.             gr_bm_ubitblt( dw-xoff, dh/2, 0, 2, xoff, 0, &RenderCanvas[0].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap);
  1586.             gr_bm_ubitblt( dw-xoff, dh/2, xoff, 3, 0, 0, &RenderCanvas[1].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap);
  1587.         } else {
  1588.             gr_bm_ubitblt( dw, dh/2, 0, 0, 0, 0, &RenderCanvas[0].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap);
  1589.             gr_bm_ubitblt( dw, dh/2, 0, 1, 0, 0, &RenderCanvas[1].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap);
  1590.             gr_bm_ubitblt( dw, dh/2, 0, 2, 0, 0, &RenderCanvas[0].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap);
  1591.             gr_bm_ubitblt( dw, dh/2, 0, 3, 0, 0, &RenderCanvas[1].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap);
  1592.         }
  1593.     } else {
  1594.         gr_bitblt_dest_step_shift = 1;      // Skip every other scanline.
  1595.         if ( VR_eye_offset > 0 )    {
  1596.             int xoff = labs(VR_eye_offset);
  1597.             gr_bm_ubitblt( dw-xoff, dh, xoff, 0, 0, 0, &RenderCanvas[0].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap);
  1598.             gr_bm_ubitblt( dw-xoff, dh, 0, 1, xoff, 0, &RenderCanvas[1].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap);
  1599.         } else if ( VR_eye_offset < 0 ) {
  1600.             int xoff = labs(VR_eye_offset);
  1601.             gr_bm_ubitblt( dw-xoff, dh, 0, 0, xoff, 0, &RenderCanvas[0].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap);
  1602.             gr_bm_ubitblt( dw-xoff, dh, xoff, 1, 0, 0, &RenderCanvas[1].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap);
  1603.         } else {
  1604.             gr_bm_ubitblt( dw, dh, 0, 0, 0, 0, &RenderCanvas[0].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap);
  1605.             gr_bm_ubitblt( dw, dh, 0, 1, 0, 0, &RenderCanvas[1].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap);
  1606.         }
  1607.     }
  1608.  
  1609.     gr_bitblt_double = 0;
  1610.     gr_bitblt_dest_step_shift = 0;
  1611.  
  1612.     if (  VR_use_paging  )  {
  1613.         gr_wait_for_retrace = 0;
  1614.  
  1615.         if ( (VR_screen_pages[VR_current_page].cv_bitmap.bm_type == BM_MODEX) && (Game_3dmax_flag==3) ) {
  1616.             int old_x, old_y, new_x;
  1617.             old_x = VR_screen_pages[VR_current_page].cv_bitmap.bm_x;
  1618.             old_y = VR_screen_pages[VR_current_page].cv_bitmap.bm_y;
  1619.             new_x = old_y*VR_screen_pages[VR_current_page].cv_bitmap.bm_rowsize;
  1620.             new_x += old_x/4;
  1621.             VR_screen_pages[VR_current_page].cv_bitmap.bm_x = new_x;
  1622.             VR_screen_pages[VR_current_page].cv_bitmap.bm_y = 0;
  1623.             VR_screen_pages[VR_current_page].cv_bitmap.bm_type = BM_SVGA;
  1624.             gr_show_canvas( &VR_screen_pages[VR_current_page] );
  1625.             VR_screen_pages[VR_current_page].cv_bitmap.bm_type = BM_MODEX;
  1626.             VR_screen_pages[VR_current_page].cv_bitmap.bm_x = old_x;
  1627.             VR_screen_pages[VR_current_page].cv_bitmap.bm_y = old_y;
  1628.         } else {
  1629.             gr_show_canvas( &VR_screen_pages[VR_current_page] );
  1630.         }
  1631.         gr_wait_for_retrace = 1;
  1632.     }
  1633.     grd_curscreen->sc_aspect=save_aspect;
  1634. }
  1635.  
  1636.  
  1637.  
  1638. //render a frame for the game
  1639. void game_render_frame_mono(void)
  1640. {
  1641.     grs_canvas Screen_3d_window;
  1642.  
  1643.     gr_init_sub_canvas( &Screen_3d_window, &VR_screen_pages[0],
  1644.             VR_render_sub_buffer[0].cv_bitmap.bm_x, VR_render_sub_buffer[0].
  1645.             cv_bitmap.bm_y, VR_render_sub_buffer[0].cv_bitmap.bm_w,
  1646.             VR_render_sub_buffer[0].cv_bitmap.bm_h);
  1647.  
  1648.     if ( Game_double_buffer )   
  1649.         gr_set_current_canvas(&VR_render_sub_buffer[0]);
  1650.     else    {
  1651.         gr_set_current_canvas(&Screen_3d_window);
  1652.     }
  1653.  
  1654.     render_frame(0);
  1655.  
  1656.     game_draw_hud_stuff();
  1657.  
  1658. #ifdef VIRGIN
  1659.     VirgeSwitchBufferWait();
  1660. #endif
  1661.  
  1662. #ifdef WARP3D
  1663.     WARP_SwitchBuffer();
  1664. #endif
  1665.  
  1666. #if !defined(VIRGIN) && !defined(WARP3D)
  1667.     if ( Game_double_buffer ) {
  1668.         if (Cockpit_mode != CM_FULL_COCKPIT && Cockpit_mode != CM_REAR_VIEW) {
  1669.             if ( VR_use_paging )    {       
  1670.                 VR_current_page = !VR_current_page;
  1671.                 gr_set_current_canvas( &VR_screen_pages[VR_current_page] );
  1672.                 gr_bm_ubitblt( VR_render_sub_buffer[0].cv_w,
  1673.                       VR_render_sub_buffer[0].cv_h, VR_render_sub_buffer[0].
  1674.                       cv_bitmap.bm_x, VR_render_sub_buffer[0].cv_bitmap.bm_y,
  1675.                       0, 0, &VR_render_sub_buffer[0].cv_bitmap,
  1676.                       &VR_screen_pages[VR_current_page].cv_bitmap );
  1677.                 gr_wait_for_retrace = 0;
  1678.                 gr_show_canvas( &VR_screen_pages[VR_current_page] );
  1679.                 gr_wait_for_retrace = 1;
  1680.             } else {
  1681.                 gr_bm_ubitblt( VR_render_sub_buffer[0].cv_w, VR_render_sub_buffer[0].cv_h, VR_render_sub_buffer[0].cv_bitmap.bm_x, VR_render_sub_buffer[0].cv_bitmap.bm_y, 0, 0, &VR_render_sub_buffer[0].cv_bitmap, &VR_screen_pages[0].cv_bitmap );
  1682.             }
  1683.         } else  {
  1684.             gr_ibitblt( &VR_render_buffer[0].cv_bitmap, &VR_screen_pages[0].cv_bitmap, Game_cockpit_double); // Game_cockpit_copy_code );
  1685.         }
  1686.     }
  1687. #endif
  1688.     if (Cockpit_mode==CM_FULL_COCKPIT || Cockpit_mode==CM_STATUS_BAR) {
  1689.  
  1690.     if (UseShareware) {
  1691.         if ( (Newdemo_state == ND_STATE_PLAYBACK) )
  1692.             Game_mode = Newdemo_game_mode;
  1693.     }
  1694.  
  1695.         render_gauges();
  1696.  
  1697.     if (UseShareware) {
  1698.         if ( (Newdemo_state == ND_STATE_PLAYBACK) )
  1699.             Game_mode = GM_NORMAL;
  1700.     }
  1701.     }
  1702.  
  1703. }
  1704.  
  1705. void game_render_frame()
  1706. {
  1707.     set_screen_mode( SCREEN_GAME );
  1708.  
  1709.     update_cockpits(0);
  1710.  
  1711.     play_homing_warning();
  1712.  
  1713.     if (VR_render_mode == VR_INTERLACED )
  1714.         game_render_frame_stereo_interlaced();
  1715.     else if (VR_render_mode == VR_AREA_DET)
  1716.         game_render_frame_stereo_vfx();
  1717.     else if (VR_render_mode == VR_NONE )
  1718.         game_render_frame_mono();       
  1719.  
  1720.     // Make sure palette is faded in
  1721.     stop_time();
  1722.     gr_palette_fade_in( gr_palette, 32, 0 );
  1723.     start_time();
  1724. #if !defined(VIRGIN) && !defined(WARP3D)
  1725.     gr_update(NULL);
  1726. #endif
  1727.  
  1728. }
  1729.  
  1730. void do_photos();
  1731. void level_with_floor();
  1732.  
  1733. void save_screen_shot(int automap_flag)
  1734. {
  1735.     fix t1;
  1736.     char message[100];
  1737.     grs_canvas *screen_canv=&grd_curscreen->sc_canvas;
  1738.     grs_font *save_font;
  1739.     static savenum=0;
  1740.     grs_canvas *temp_canv,*save_canv;
  1741.     char savename[13];
  1742.     ubyte pal[768];
  1743.     int w,h,aw,x,y;
  1744.  
  1745.     // Can't do screen shots in VR modes.
  1746.     if ( VR_render_mode != VR_NONE )
  1747.         return;
  1748.  
  1749.     stop_time();
  1750.  
  1751.     save_canv = grd_curcanv;
  1752.     temp_canv = gr_create_canvas(screen_canv->cv_bitmap.bm_w,screen_canv->cv_bitmap.bm_h);
  1753.     gr_set_current_canvas(temp_canv);
  1754.     gr_ubitmap(0,0,&screen_canv->cv_bitmap);
  1755.  
  1756.     if ( savenum > 99 ) savenum = 0;
  1757.     sprintf(savename,"screen%02d.pcx",savenum++);
  1758.     sprintf( message, "%s '%s'", TXT_DUMPING_SCREEN, savename );
  1759.  
  1760.     gr_set_current_canvas(&VR_screen_pages[VR_current_page]);
  1761.     save_font = grd_curcanv->cv_font;
  1762.     gr_set_curfont(GAME_FONT);
  1763.     gr_set_fontcolor(gr_find_closest_color_current(0,31,0),-1);
  1764.     gr_get_string_size(message,&w,&h,&aw);
  1765.     x = (VR_screen_pages[VR_current_page].cv_w-w)/2;
  1766.     y = (VR_screen_pages[VR_current_page].cv_h-h)/2;
  1767.  
  1768.     if (automap_flag) {
  1769.         modex_print_message(32, y, message);
  1770.     } else {
  1771.         gr_setcolor(gr_find_closest_color_current(0,0,0));
  1772.         gr_rect(x-2,y-2,x+w+2,y+h+2);
  1773.         gr_printf(x,y,message);
  1774.         gr_set_curfont(save_font);
  1775.     }
  1776.     t1 = timer_get_fixed_seconds() + F1_0;
  1777.  
  1778.     gr_palette_read(pal);       //get actual palette from the hardware
  1779.     pcx_write_bitmap(savename,&temp_canv->cv_bitmap,pal);
  1780.  
  1781.     while ( timer_get_fixed_seconds() < t1 );       // Wait so that messag stays up at least 1 second.
  1782.  
  1783.     gr_set_current_canvas(screen_canv);
  1784.  
  1785.     if (!automap_flag)
  1786.         gr_ubitmap(0,0,&temp_canv->cv_bitmap);
  1787.  
  1788.     gr_free_canvas(temp_canv);
  1789.  
  1790.     gr_set_current_canvas(save_canv);
  1791.     key_flush();
  1792.     start_time();
  1793. }
  1794.  
  1795. //initialize flying
  1796. fly_init(object *obj)
  1797. {
  1798.     obj->control_type = CT_FLYING;
  1799.     obj->movement_type = MT_PHYSICS;
  1800.  
  1801.     vm_vec_zero(&obj->mtype.phys_info.velocity);
  1802.     vm_vec_zero(&obj->mtype.phys_info.thrust);
  1803.     vm_vec_zero(&obj->mtype.phys_info.rotvel);
  1804.     vm_vec_zero(&obj->mtype.phys_info.rotthrust);
  1805. }
  1806.     
  1807. //void morph_test(), morph_step();
  1808.  
  1809. int sound_nums[] = {10,11,20,21,30,31,32,33,40,41,50,51,60,61,62,70,80,81,82,83,90,91};
  1810.  
  1811. #define N_TEST_SOUNDS (sizeof(sound_nums) / sizeof(*sound_nums))
  1812.  
  1813. int test_sound_num=0;
  1814.  
  1815. play_test_sound()
  1816. {
  1817.  
  1818.     digi_play_sample(sound_nums[test_sound_num], F1_0);
  1819. }
  1820.  
  1821. //  ------------------------------------------------------------------------------------
  1822. advance_sound()
  1823. {
  1824.     if (++test_sound_num == N_TEST_SOUNDS)
  1825.         test_sound_num=0;
  1826.  
  1827. }
  1828.  
  1829. test_anim_states();
  1830.  
  1831. #include "fvi.h"
  1832.  
  1833. //put up the help message
  1834. void do_show_help()
  1835. {
  1836. //  if (!((Game_mode & GM_MULTI) && (Function_mode == FMODE_GAME)))
  1837. //      stop_time();
  1838.  
  1839.     show_help();
  1840.  
  1841. //  if (!((Game_mode & GM_MULTI) && (Function_mode == FMODE_GAME)))
  1842. //      start_time();
  1843.  
  1844. }
  1845.  
  1846. //--unused-- int save_newdemo_state;
  1847.  
  1848. extern int been_in_editor;
  1849.  
  1850. //--killed--//  ------------------------------------------------------------------------------------
  1851. //--killed--//  Return 1 if toggled, else return 0.
  1852. //--killed--//  Might not be able to toggle if off and not allowed to turn on.
  1853. //--killed--int toggle_afterburner_status(void)
  1854. //--killed--{
  1855. //--killed--    player  *pp = &Players[Player_num];
  1856. //--killed--
  1857. //--killed--    if (!(pp->flags & PLAYER_FLAGS_AFTERBURNER)) {
  1858. //--killed--        //  Was off, try to turn on.
  1859. //--killed--        if ((pp->afterburner_time > AFTERBURNER_MAX_TIME/4) && (pp->energy > 0)) {
  1860. //--killed--            pp->flags |= PLAYER_FLAGS_AFTERBURNER;
  1861. //--killed--        } else {
  1862. //--killed--            mprintf(0, "Cannot turn on afterburner due to energy or recharge.\n");
  1863. //--killed--            return 0;
  1864. //--killed--        }
  1865. //--killed--        return 1;
  1866. //--killed--    } else {
  1867. //--killed--        pp->flags ^= PLAYER_FLAGS_AFTERBURNER;
  1868. //--killed--        return 1;
  1869. //--killed--    }
  1870. //--killed--}
  1871.  
  1872. //  ------------------------------------------------------------------------------------
  1873. void do_cloak_stuff(void)
  1874. {
  1875.     int i;
  1876.     for (i = 0; i < N_players; i++)
  1877.         if (Players[i].flags & PLAYER_FLAGS_CLOAKED) {
  1878.             // mprintf(0, "Cloak time left: %7.3f\n", f2fl(CLOAK_TIME_MAX - (GameTime - Players[Player_num].cloak_time)));
  1879.             if (GameTime - Players[i].cloak_time > CLOAK_TIME_MAX) {
  1880.                 Players[i].flags &= ~PLAYER_FLAGS_CLOAKED;
  1881.                 if (i == Player_num) {
  1882.                     digi_play_sample( SOUND_CLOAK_OFF, F1_0);
  1883.                     #ifdef NETWORK
  1884.                     if (Game_mode & GM_MULTI)
  1885.                         multi_send_play_sound(SOUND_CLOAK_OFF, F1_0);
  1886.                     maybe_drop_net_powerup(POW_CLOAK);
  1887.                     multi_send_decloak(); // For demo recording
  1888.                     #endif
  1889. //                  mprintf((0, " --- You have been DE-CLOAKED! ---\n"));
  1890.                 }
  1891.             }
  1892.         }
  1893. }
  1894.  
  1895. //  ------------------------------------------------------------------------------------
  1896. void do_invulnerable_stuff(void)
  1897. {
  1898.     if (Players[Player_num].flags & PLAYER_FLAGS_INVULNERABLE) {
  1899.         if (GameTime - Players[Player_num].invulnerable_time > INVULNERABLE_TIME_MAX) {
  1900.             Players[Player_num].flags ^= PLAYER_FLAGS_INVULNERABLE;
  1901.             #ifdef NETWORK
  1902.             maybe_drop_net_powerup(POW_INVULNERABILITY);
  1903.             #endif
  1904.             digi_play_sample( SOUND_INVULNERABILITY_OFF, F1_0);
  1905.             #ifdef NETWORK
  1906.             if (Game_mode & GM_MULTI)
  1907.                 multi_send_play_sound(SOUND_INVULNERABILITY_OFF, F1_0);
  1908.             #endif
  1909.             mprintf((0, " --- You have been DE-INVULNERABLEIZED! ---\n"));
  1910.         }
  1911.     }
  1912. }
  1913.     
  1914. //--killed--//  ------------------------------------------------------------------------------------
  1915. //--killed--void do_afterburner_stuff(void)
  1916. //--killed--{
  1917. //--killed--    player  *pp = &Players[Player_num];
  1918. //--killed--
  1919. //--killed--//  mprintf(0, "[Afterburner] Time: %7.3f, status = %i\n", f2fl(pp->afterburner_time), pp->flags & PLAYER_FLAGS_AFTERBURNER);
  1920. //--killed--
  1921. //--killed--    if (pp->flags & PLAYER_FLAGS_AFTERBURNER) {
  1922. //--killed--        if (pp->afterburner_time > 0) {
  1923. //--killed--            pp->afterburner_time -= FrameTime;
  1924. //--killed--            pp->energy -= FrameTime/2;
  1925. //--killed--            if (pp->afterburner_time <= 0) {
  1926. //--killed--                pp->afterburner_time = 0;
  1927. //--killed--                pp->flags &= ~PLAYER_FLAGS_AFTERBURNER;
  1928. //--killed--                say_afterburner_status();
  1929. //--killed--            }
  1930. //--killed--            if (pp->energy <= 0) {
  1931. //--killed--                pp->energy = 0;
  1932. //--killed--                pp->flags &= ~PLAYER_FLAGS_AFTERBURNER;
  1933. //--killed--                say_afterburner_status();
  1934. //--killed--            }
  1935. //--killed--        }
  1936. //--killed--    } else {
  1937. //--killed--        //  Since afterburner is probably almost always max, do the check, we save time.
  1938. //--killed--        if (pp->afterburner_time < AFTERBURNER_MAX_TIME) {
  1939. //--killed--            pp->afterburner_time += FrameTime/2;
  1940. //--killed--            if (pp->afterburner_time > AFTERBURNER_MAX_TIME)
  1941. //--killed--                pp->afterburner_time = AFTERBURNER_MAX_TIME;
  1942. //--killed--        }
  1943. //--killed--    }
  1944. //--killed--
  1945. //--killed--}
  1946.  
  1947. //  Amount to diminish guns towards normal, per second.
  1948. #define DIMINISH_RATE   16      //  gots to be a power of 2, else change the code in diminish_palette_towards_normal
  1949.  
  1950. //  ------------------------------------------------------------------------------------
  1951. //  Diminish palette effects towards normal.
  1952. void diminish_palette_towards_normal(void)
  1953. {
  1954.     int dec_amount = 0;
  1955.  
  1956.     //  Diminish at DIMINISH_RATE units/second.
  1957.     //  For frame rates > DIMINISH_RATE Hz, use randomness to achieve this.
  1958.     if (FrameTime < F1_0/DIMINISH_RATE) {
  1959.         if (rand() < FrameTime*DIMINISH_RATE/2) //  Note: rand() is in 0..32767, and 8 Hz means decrement every frame
  1960.             dec_amount = 1;
  1961.     } else {
  1962.         dec_amount = f2i(FrameTime*DIMINISH_RATE);      // one second = DIMINISH_RATE counts
  1963.         if (dec_amount == 0)
  1964.             dec_amount++;                       // make sure we decrement by something
  1965.     }
  1966.  
  1967.     if (PaletteRedAdd > 0 ) { PaletteRedAdd -= dec_amount; if (PaletteRedAdd < 0 ) PaletteRedAdd = 0; }
  1968.     if (PaletteRedAdd < 0 ) { PaletteRedAdd += dec_amount; if (PaletteRedAdd > 0 ) PaletteRedAdd = 0; }
  1969.  
  1970.     if (PaletteGreenAdd > 0 ) { PaletteGreenAdd -= dec_amount; if (PaletteGreenAdd < 0 ) PaletteGreenAdd = 0; }
  1971.     if (PaletteGreenAdd < 0 ) { PaletteGreenAdd += dec_amount; if (PaletteGreenAdd > 0 ) PaletteGreenAdd = 0; }
  1972.  
  1973.     if (PaletteBlueAdd > 0 ) { PaletteBlueAdd -= dec_amount; if (PaletteBlueAdd < 0 ) PaletteBlueAdd = 0; }
  1974.     if (PaletteBlueAdd < 0 ) { PaletteBlueAdd += dec_amount; if (PaletteBlueAdd > 0 ) PaletteBlueAdd = 0; }
  1975.  
  1976.     if ( (Newdemo_state==ND_STATE_RECORDING) && (PaletteRedAdd || PaletteGreenAdd || PaletteBlueAdd) )
  1977.         newdemo_record_palette_effect(PaletteRedAdd, PaletteGreenAdd, PaletteBlueAdd);
  1978.  
  1979.     gr_palette_step_up( PaletteRedAdd, PaletteGreenAdd, PaletteBlueAdd );
  1980.  
  1981.     //mprintf(0, "%2i %2i %2i\n", PaletteRedAdd, PaletteGreenAdd, PaletteBlueAdd);
  1982.  
  1983.     // need to reset black and white palette colors for SVR registration
  1984.     if (Game_simuleyes_flag)  {
  1985.         // make black be black      
  1986.     }
  1987. }
  1988.  
  1989. int Redsave, Bluesave, Greensave;
  1990.  
  1991. void palette_save(void)
  1992. {
  1993.     Redsave = PaletteRedAdd; Bluesave = PaletteBlueAdd; Greensave = PaletteGreenAdd;
  1994. }
  1995.  
  1996. void palette_restore(void)
  1997. {
  1998.     PaletteRedAdd = Redsave; PaletteBlueAdd = Bluesave; PaletteGreenAdd = Greensave;
  1999.     gr_palette_step_up( PaletteRedAdd, PaletteGreenAdd, PaletteBlueAdd );
  2000. }
  2001.  
  2002. extern void dead_player_frame(void);
  2003.  
  2004. #ifndef RELEASE
  2005. do_cheat_menu()
  2006. {
  2007.     int mmn;
  2008.     newmenu_item mm[16];
  2009.     char score_text[21];
  2010.  
  2011.     sprintf( score_text, "%d", Players[Player_num].score );
  2012.  
  2013.     mm[0].type=NM_TYPE_CHECK; mm[0].value=Players[Player_num].flags & PLAYER_FLAGS_INVULNERABLE; mm[0].text="Invulnerability";
  2014.     mm[1].type=NM_TYPE_CHECK; mm[1].value=Players[Player_num].flags & PLAYER_FLAGS_IMMATERIAL; mm[1].text="Immaterial";
  2015.     mm[2].type=NM_TYPE_CHECK; mm[2].value=0; mm[2].text="All keys";
  2016.     mm[3].type=NM_TYPE_NUMBER; mm[3].value=f2i(Players[Player_num].energy); mm[3].text="% Energy"; mm[3].min_value=0; mm[3].max_value=200;
  2017.     mm[4].type=NM_TYPE_NUMBER; mm[4].value=f2i(Players[Player_num].shields); mm[4].text="% Shields"; mm[4].min_value=0; mm[4].max_value=200;
  2018.     mm[5].type=NM_TYPE_TEXT; mm[5].text = "Score:";
  2019.     mm[6].type=NM_TYPE_INPUT; mm[6].text_len = 10; mm[6].text = score_text;
  2020.     mm[7].type=NM_TYPE_RADIO; mm[7].value=(Players[Player_num].laser_level==0); mm[7].group=0; mm[7].text="Laser level 1";
  2021.     mm[8].type=NM_TYPE_RADIO; mm[8].value=(Players[Player_num].laser_level==1); mm[8].group=0; mm[8].text="Laser level 2";
  2022.     mm[9].type=NM_TYPE_RADIO; mm[9].value=(Players[Player_num].laser_level==2); mm[9].group=0; mm[9].text="Laser level 3";
  2023.     mm[10].type=NM_TYPE_RADIO; mm[10].value=(Players[Player_num].laser_level==3); mm[10].group=0; mm[10].text="Laser level 4";
  2024.     mm[11].type=NM_TYPE_NUMBER; mm[11].value=Players[Player_num].secondary_ammo[CONCUSSION_INDEX]; mm[11].text="Missiles"; mm[11].min_value=0; mm[11].max_value=200;
  2025.  
  2026.     mmn = newmenu_do("Wimp Menu",NULL,12, mm, NULL );
  2027.  
  2028.     if (mmn > -1 )  {
  2029.         if ( mm[0].value )  {
  2030.             Players[Player_num].flags |= PLAYER_FLAGS_INVULNERABLE;
  2031.             Players[Player_num].invulnerable_time = GameTime+i2f(1000);
  2032.         } else
  2033.             Players[Player_num].flags &= ~PLAYER_FLAGS_INVULNERABLE;
  2034.         if ( mm[1].value ) 
  2035.             Players[Player_num].flags |= PLAYER_FLAGS_IMMATERIAL;
  2036.         else
  2037.             Players[Player_num].flags &= ~PLAYER_FLAGS_IMMATERIAL;
  2038.         if (mm[2].value) Players[Player_num].flags |= PLAYER_FLAGS_BLUE_KEY | PLAYER_FLAGS_RED_KEY | PLAYER_FLAGS_GOLD_KEY;
  2039.         Players[Player_num].energy=i2f(mm[3].value);
  2040.         Players[Player_num].shields=i2f(mm[4].value);
  2041.         Players[Player_num].score = atoi(mm[6].text);
  2042.         if (mm[7].value) Players[Player_num].laser_level=0;
  2043.         if (mm[8].value) Players[Player_num].laser_level=1;
  2044.         if (mm[9].value) Players[Player_num].laser_level=2;
  2045.         if (mm[10].value) Players[Player_num].laser_level=3;
  2046.         Players[Player_num].secondary_ammo[CONCUSSION_INDEX] = mm[11].value;
  2047.         init_gauges();
  2048.     }
  2049. }
  2050. #endif
  2051.  
  2052. //  --------------------------------------------------------------------------------------------------
  2053. int allowed_to_fire_laser(void)
  2054. {
  2055.     if (Player_is_dead) {
  2056.         Global_missile_firing_count = 0;
  2057.         return 0;
  2058.     }
  2059.  
  2060.     //  Make sure enough time has elapsed to fire laser, but if it looks like it will
  2061.     //  be a long while before laser can be fired, then there must be some mistake!
  2062.     if (Next_laser_fire_time > GameTime)
  2063.         if (Next_laser_fire_time < GameTime + 2*F1_0)
  2064.             return 0;
  2065.  
  2066.     return 1;
  2067. }
  2068.  
  2069. fix Next_flare_fire_time = 0;
  2070.  
  2071. int allowed_to_fire_flare(void)
  2072. {
  2073.     if (Next_flare_fire_time > GameTime)
  2074.         if (Next_flare_fire_time < GameTime + F1_0) //  In case time is bogus, never wait > 1 second.
  2075.             return 0;
  2076.  
  2077.     Next_flare_fire_time = GameTime + F1_0/4;
  2078.  
  2079.     return 1;
  2080. }
  2081.  
  2082. int allowed_to_fire_missile(void)
  2083. {
  2084. // mprintf(0, "Next fire = %7.3f, Cur time = %7.3f\n", f2fl(Next_missile_fire_time), f2fl(GameTime));
  2085.     //  Make sure enough time has elapsed to fire missile, but if it looks like it will
  2086.     //  be a long while before missile can be fired, then there must be some mistake!
  2087.     if (Next_missile_fire_time > GameTime)
  2088.         if (Next_missile_fire_time < GameTime + 5*F1_0)
  2089.             return 0;
  2090.  
  2091.     return 1;
  2092. }
  2093.  
  2094. typedef struct bkg {
  2095.     short x, y, w, h;           // The location of the menu.
  2096.     grs_bitmap * bmp;           // The background under the menu.
  2097. } bkg;
  2098.  
  2099. bkg bg = {0,0,0,0,NULL};
  2100.  
  2101. //show a message in a nice little box
  2102. void show_boxed_message(char *msg)
  2103. {   
  2104.     int w,h,aw;
  2105.     int x,y;
  2106.  
  2107.     gr_set_current_canvas(&VR_screen_pages[VR_current_page]);
  2108.     gr_set_curfont( HELP_FONT );
  2109.  
  2110.     gr_get_string_size(msg,&w,&h,&aw);
  2111.  
  2112.     x = (grd_curscreen->sc_w-w)/2;
  2113.     y = (grd_curscreen->sc_h-h)/2;
  2114.  
  2115.     if (bg.bmp) {
  2116.         gr_free_bitmap(bg.bmp);
  2117.         bg.bmp = NULL;
  2118.     }
  2119.  
  2120.     // Save the background of the display
  2121.     bg.x=x; bg.y=y; bg.w=w; bg.h=h;
  2122.  
  2123.     bg.bmp = gr_create_bitmap( w+30, h+30 );
  2124.     gr_bm_ubitblt(w+30, h+30, 0, 0, x-15, y-15, &(grd_curscreen->sc_canvas.cv_bitmap), bg.bmp );
  2125.  
  2126.     nm_draw_background(x-15,y-15,x+w+15-1,y+h+15-1);
  2127.  
  2128.     gr_set_fontcolor( gr_getcolor(31, 31, 31), -1 );
  2129.     gr_ustring( 0x8000, y, msg );
  2130.     gr_update(NULL);
  2131.  
  2132. }
  2133.  
  2134. void clear_boxed_message()
  2135. {
  2136.  
  2137.     if (bg.bmp) {
  2138.  
  2139.         gr_bitmap(bg.x-15, bg.y-15, bg.bmp);
  2140.  
  2141.         gr_free_bitmap(bg.bmp);
  2142.  
  2143.         bg.bmp = NULL;
  2144.     }
  2145. }
  2146.  
  2147. extern int Death_sequence_aborted;
  2148.  
  2149. //Process selected keys until game unpaused. returns key that left pause (p or esc)
  2150. int do_game_pause(int allow_menu)
  2151. {
  2152.     int paused;
  2153.     int key;
  2154.  
  2155.  
  2156.     if (Game_mode & GM_MULTI)
  2157.     {
  2158.         HUD_init_message(TXT_CANT_PAUSE);
  2159.         return(KEY_PAUSE);
  2160.     }
  2161.  
  2162.     digi_pause_all();
  2163.     stop_time();
  2164.  
  2165.     gr_printf(0x8000, 30, "PAUSE");
  2166.  
  2167.     palette_save();
  2168.     reset_palette_add();
  2169.  
  2170.     game_flush_inputs();
  2171.  
  2172.     paused=1;
  2173. /*
  2174.     set_screen_mode( SCREEN_MENU );
  2175.     gr_palette_load( gr_palette );
  2176.  
  2177.     show_boxed_message(TXT_PAUSE);
  2178.  
  2179.     while (paused) {
  2180.  
  2181.         key = key_getch();
  2182.  
  2183.         switch (key) {
  2184.             case 0:
  2185.                 break;
  2186.  
  2187.             case KEY_ESC:
  2188.                 if (allow_menu)
  2189.                     Function_mode = FMODE_MENU;
  2190.                 clear_boxed_message();
  2191.                 paused=0;
  2192.                 break;
  2193.  
  2194.             case KEY_F1:
  2195.                 clear_boxed_message();
  2196.                 do_show_help();
  2197.                 show_boxed_message(TXT_PAUSE);
  2198.                 break;
  2199.  
  2200.             case KEY_ALTED+KEY_PADMULTIPLY:
  2201.                 save_screen_shot(0);
  2202.                 break;
  2203.  
  2204.             #ifndef RELEASE
  2205.             case KEY_BACKSP: Int3(); break;
  2206.             #endif
  2207.  
  2208.             default:
  2209.                 clear_boxed_message();
  2210.                 paused=0;
  2211.                 break;
  2212.  
  2213.         }
  2214.  
  2215.     }
  2216. */
  2217.     while (paused) {
  2218.  
  2219.         key = key_getch();
  2220.  
  2221.         switch (key) {
  2222.             case 0:
  2223.                 break;
  2224.  
  2225.             case KEY_ESC:
  2226.                 if (allow_menu)
  2227.                     Function_mode = FMODE_MENU;
  2228.                 paused=0;
  2229.                 break;
  2230.  
  2231.             case KEY_ALTED+KEY_PADMULTIPLY:
  2232.                 save_screen_shot(0);
  2233.                 break;
  2234.  
  2235.             case KEY_PAUSE:
  2236.                 paused=0;
  2237.                 break;
  2238.  
  2239.         }
  2240.  
  2241.     }
  2242.  
  2243.     game_flush_inputs();
  2244.  
  2245.     palette_restore();
  2246.  
  2247.     start_time();
  2248.     digi_resume_all();
  2249.  
  2250.     HUD_init_message("ACTION!");
  2251.  
  2252.     return key;
  2253. }
  2254.  
  2255.  
  2256. void show_help()
  2257. {
  2258.     newmenu_item m[14];
  2259.  
  2260.     if ( VR_render_mode != VR_NONE )    {
  2261.         m[ 0].type = NM_TYPE_TEXT; m[ 0].text = TXT_HELP_ESC;
  2262.         m[ 1].type = NM_TYPE_TEXT; m[ 1].text = TXT_HELP_ALT_F2;
  2263.         m[ 2].type = NM_TYPE_TEXT; m[ 2].text = TXT_HELP_ALT_F3;
  2264.         m[ 3].type = NM_TYPE_TEXT; m[ 3].text = TXT_HELP_F2;
  2265.         m[ 4].type = NM_TYPE_TEXT; m[ 4].text = TXT_HELP_F4;
  2266.         m[ 5].type = NM_TYPE_TEXT; m[ 5].text = TXT_HELP_F5;
  2267.         m[ 6].type = NM_TYPE_TEXT; m[ 6].text = TXT_HELP_PAUSE;
  2268.         m[ 7].type = NM_TYPE_TEXT; m[ 7].text = TXT_HELP_1TO5;
  2269.         m[ 8].type = NM_TYPE_TEXT; m[ 8].text = TXT_HELP_6TO10;
  2270.         m[ 9].type = NM_TYPE_TEXT; m[ 9].text = "";
  2271.         m[10].type = NM_TYPE_TEXT; m[10].text = TXT_HELP_TO_VIEW;
  2272.         newmenu_do( NULL, TXT_KEYS, 11, m, NULL );
  2273.     } else {
  2274.         m[ 0].type = NM_TYPE_TEXT; m[ 0].text = TXT_HELP_ESC;
  2275.         m[ 1].type = NM_TYPE_TEXT; m[ 1].text = TXT_HELP_ALT_F2;
  2276.         m[ 2].type = NM_TYPE_TEXT; m[ 2].text = TXT_HELP_ALT_F3;
  2277.         m[ 3].type = NM_TYPE_TEXT; m[ 3].text = TXT_HELP_F2;
  2278.         m[ 4].type = NM_TYPE_TEXT; m[ 4].text = TXT_HELP_F3;
  2279.         m[ 5].type = NM_TYPE_TEXT; m[ 5].text = TXT_HELP_F4;
  2280.         m[ 6].type = NM_TYPE_TEXT; m[ 6].text = TXT_HELP_F5;
  2281.         m[ 7].type = NM_TYPE_TEXT; m[ 7].text = TXT_HELP_PAUSE;
  2282.         m[ 8].type = NM_TYPE_TEXT; m[ 8].text = TXT_HELP_MINUSPLUS;
  2283.         m[ 9].type = NM_TYPE_TEXT; m[ 9].text = TXT_HELP_PRTSCN;
  2284.         m[10].type = NM_TYPE_TEXT; m[10].text = TXT_HELP_1TO5;
  2285.         m[11].type = NM_TYPE_TEXT; m[11].text = TXT_HELP_6TO10;
  2286.         m[12].type = NM_TYPE_TEXT; m[12].text = "";
  2287.         m[13].type = NM_TYPE_TEXT; m[13].text = TXT_HELP_TO_VIEW;
  2288.         newmenu_do( NULL, TXT_KEYS, 14, m, NULL );
  2289.     }
  2290.  
  2291. }
  2292.  
  2293.  
  2294. #ifdef ARCADE
  2295. void arcade_frame_info()
  2296. {
  2297.     if (!Arcade_mode) return;
  2298.  
  2299.     if ( Newdemo_state == ND_STATE_PLAYBACK )   {
  2300.         gr_set_curfont( GAME_FONT );    //game_font );
  2301.         gr_set_fontcolor(gr_getcolor(0,31,0), -1 );
  2302.         gr_printf(0x8000, 5, "Insert Coins to Play" );
  2303.         return;
  2304.     } 
  2305.  
  2306.     if (Arcade_timer > 0 )  {
  2307.         gr_set_curfont( GAME_FONT );
  2308.         gr_set_fontcolor( gr_getcolor(0, 31, 0), -1 );
  2309.         gr_printf( 0x8000, 5, "%d seconds left", f2i(Arcade_timer) );
  2310.     } else {
  2311.         gr_set_curfont( Gamefonts[GFONT_BIG_1] );    //GAME_FONT );
  2312.         gr_printf(0x8000, 40, "Game Over" );
  2313.     
  2314.         gr_set_curfont( Gamefonts[GFONT_MEDIUM_2] );    //GAME_FONT );
  2315.         gr_printf(0x8000, 60, "Insert Coins to Continue" );
  2316.         gr_printf(0x8000, 75, "%d", f2i(Arcade_timer)+10 );
  2317.     }   
  2318. }
  2319. #endif
  2320.  
  2321. //temp function until Matt cleans up game sequencing
  2322. extern void temp_reset_stuff_on_level();
  2323.  
  2324. //deal with rear view - switch it on, or off, or whatever
  2325. check_rear_view()
  2326. {
  2327.  
  2328.     #define LEAVE_TIME 0x4000       //how long until we decide key is down  (Used to be 0x4000)
  2329.  
  2330.     static int leave_mode;
  2331.     static fix entry_time;
  2332.  
  2333.     if ( Controls.rear_view_down_count )    {       //key/button has gone down
  2334.  
  2335.         if (Rear_view) {
  2336.             Rear_view = 0;
  2337.             if (Cockpit_mode==CM_REAR_VIEW) {
  2338.                 select_cockpit(old_cockpit_mode);
  2339.             }
  2340.             if (Newdemo_state == ND_STATE_RECORDING)
  2341.                 newdemo_record_restore_rearview();
  2342.         }
  2343.         else {
  2344.             Rear_view = 1;
  2345.             leave_mode = 0;     //means wait for another key
  2346.             entry_time = timer_get_fixed_seconds();
  2347.             if (Cockpit_mode == CM_FULL_COCKPIT) {
  2348.                 old_cockpit_mode = Cockpit_mode;
  2349.                 select_cockpit(CM_REAR_VIEW);
  2350.             }
  2351.             if (Newdemo_state == ND_STATE_RECORDING)
  2352.                 newdemo_record_rearview();
  2353.         }
  2354.     }
  2355.     else
  2356.         if (Controls.rear_view_down_state) {
  2357.  
  2358.             if (leave_mode==0 && (timer_get_fixed_seconds()-entry_time)>LEAVE_TIME)
  2359.                 leave_mode = 1;
  2360.         }
  2361.         else {
  2362.  
  2363.             //@@if (leave_mode==1 && Cockpit_mode==CM_REAR_VIEW) {
  2364.  
  2365.             if (leave_mode==1 && Rear_view) {
  2366.                 Rear_view = 0;
  2367.                 if (Cockpit_mode==CM_REAR_VIEW) {
  2368.                     select_cockpit(old_cockpit_mode); 
  2369.                 }
  2370.                 if (Newdemo_state == ND_STATE_RECORDING)
  2371.                     newdemo_record_restore_rearview();
  2372.             }
  2373.         }
  2374. }
  2375.  
  2376. void reset_rear_view(void)
  2377. {
  2378.     if (Rear_view) {
  2379.         if (Newdemo_state == ND_STATE_RECORDING)
  2380.             newdemo_record_restore_rearview();
  2381.     }
  2382.  
  2383.     Rear_view = 0;
  2384.  
  2385.     if (Cockpit_mode == CM_REAR_VIEW)
  2386.         select_cockpit(old_cockpit_mode);
  2387.  
  2388. }
  2389.  
  2390. #ifdef ARCADE
  2391. int keys_override;
  2392. #endif
  2393.  
  2394. int Automap_flag;
  2395. int Config_menu_flag;
  2396.  
  2397. jmp_buf LeaveGame;
  2398.  
  2399.  
  2400. #ifndef FINAL_CHEATS
  2401. ubyte cheat_enable_keys[] = {KEY_G,KEY_A,KEY_B,KEY_B,KEY_A,KEY_G,KEY_A,KEY_B,KEY_B,KEY_A,KEY_H,KEY_E,KEY_Y};
  2402. #endif
  2403.  
  2404. byte    Enable_john_cheat_1, Enable_john_cheat_2, Enable_john_cheat_3, Enable_john_cheat_4;
  2405.  
  2406. int cheat_enable_index;
  2407. #define CHEAT_ENABLE_LENGTH (sizeof(cheat_enable_keys) / sizeof(*cheat_enable_keys))
  2408.  
  2409. #ifdef FINAL_CHEATS
  2410. ubyte cheat_enable_keys[] = {KEY_G,KEY_A,KEY_B,KEY_B,KEY_A,KEY_G,KEY_A,KEY_B,KEY_B,KEY_A,KEY_H,KEY_E,KEY_Y};
  2411.  
  2412. ubyte cheat_wowie[] = {KEY_S,KEY_C,KEY_O,KEY_U,KEY_R,KEY_G,KEY_E};
  2413. ubyte cheat_allkeys[] = {KEY_M,KEY_I,KEY_T,KEY_Z,KEY_I};
  2414. ubyte cheat_invuln[] = {KEY_R,KEY_A,KEY_C,KEY_E,KEY_R,KEY_X};
  2415. ubyte cheat_cloak[] = {KEY_G,KEY_U,KEY_I,KEY_L,KEY_E};
  2416. ubyte cheat_shield[] = {KEY_T,KEY_W,KEY_I,KEY_L,KEY_I,KEY_G,KEY_H,KEY_T};
  2417. ubyte cheat_warp[] = {KEY_F,KEY_A,KEY_R,KEY_M,KEY_E,KEY_R,KEY_J,KEY_O,KEY_E};
  2418. ubyte cheat_astral[] = {KEY_A,KEY_S,KEY_T,KEY_R,KEY_A,KEY_L};
  2419.  
  2420. #define NUM_NEW_CHEATS 5
  2421.  
  2422. #define CHEAT_WOWIE_LENGTH (sizeof(cheat_wowie) / sizeof(*cheat_wowie))
  2423. #define CHEAT_ALLKEYS_LENGTH (sizeof(cheat_allkeys) / sizeof(*cheat_allkeys))
  2424. #define CHEAT_INVULN_LENGTH (sizeof(cheat_invuln) / sizeof(*cheat_invuln))
  2425. #define CHEAT_CLOAK_LENGTH (sizeof(cheat_cloak) / sizeof(*cheat_cloak))
  2426. #define CHEAT_SHIELD_LENGTH (sizeof(cheat_shield) / sizeof(*cheat_shield))
  2427. #define CHEAT_WARP_LENGTH (sizeof(cheat_warp) / sizeof(*cheat_warp))
  2428. #define CHEAT_ASTRAL_LENGTH (sizeof(cheat_astral) / sizeof(*cheat_astral))
  2429.  
  2430. #define CHEAT_TURBOMODE_OFS 0
  2431. #define CHEAT_WOWIE2_OFS        1
  2432. #define CHEAT_NEWLIFE_OFS       2
  2433. #define CHEAT_EXITPATH_OFS      3
  2434. #define CHEAT_ROBOTPAUSE_OFS    4
  2435.  
  2436. #define CHEAT_TURBOMODE_LENGTH  6
  2437. #define CHEAT_WOWIE2_LENGTH     6
  2438. #define CHEAT_NEWLIFE_LENGTH        5
  2439. #define CHEAT_EXITPATH_LENGTH       5
  2440. #define CHEAT_ROBOTPAUSE_LENGTH 6
  2441.  
  2442. int cheat_wowie_index;
  2443. int cheat_allkeys_index;
  2444. int cheat_invuln_index;
  2445. int cheat_cloak_index;
  2446. int cheat_shield_index;
  2447. int cheat_warp_index;
  2448. int cheat_astral_index;
  2449. int cheat_turbomode_index;
  2450. int cheat_wowie2_index;
  2451. int cheat_newlife_index;
  2452. int cheat_exitpath_index;
  2453. int cheat_robotpause_index;
  2454.  
  2455. #endif
  2456.  
  2457. int Cheats_enabled=0;
  2458.  
  2459. extern int Laser_rapid_fire, Ugly_robot_cheat;
  2460. extern void do_lunacy_on(), do_lunacy_off();
  2461.  
  2462. extern int Physics_cheat_flag;
  2463.  
  2464. void game_disable_cheats()
  2465. {
  2466.     Game_turbo_mode = 0;
  2467.     Cheats_enabled=0;
  2468.     do_lunacy_off();
  2469.     Laser_rapid_fire = 0;
  2470.     Ugly_robot_cheat = 0;
  2471.     Physics_cheat_flag = 0;
  2472. }
  2473.  
  2474. //  ------------------------------------------------------------------------------------
  2475. //this function is the game.  called when game mode selected.  runs until
  2476. //editor mode or exit selected
  2477. void game()
  2478. {
  2479. #ifdef DEBUG_PROFILE
  2480.     fix start_time = timer_get_fixed_seconds();
  2481. #endif
  2482.  
  2483.     //@@int demo_playing=0;
  2484.     //@@int multi_game=0;
  2485.  
  2486.     do_lunacy_on();     //  Copy values for insane into copy buffer in ai.c
  2487.     do_lunacy_off();        //  Restore true insane mode.
  2488.  
  2489.     Game_aborted = 0;
  2490.     last_drawn_cockpit[0] = -1;             // Force cockpit to redraw next time a frame renders.
  2491.     last_drawn_cockpit[1] = -1;             // Force cockpit to redraw next time a frame renders.
  2492.     Endlevel_sequence = 0;
  2493.  
  2494.     cheat_enable_index = 0;
  2495.  
  2496. #ifdef FINAL_CHEATS
  2497.     cheat_wowie_index = cheat_allkeys_index = cheat_invuln_index = cheat_cloak_index = cheat_shield_index = cheat_warp_index = cheat_astral_index = 0;
  2498.     cheat_turbomode_index = cheat_wowie2_index = 0;
  2499. #endif
  2500.  
  2501.     //@@if ( Newdemo_state == ND_STATE_PLAYBACK )
  2502.     //@@    demo_playing = 1;
  2503.     //@@if ( Game_mode & GM_MULTI )
  2504.     //@@    multi_game = 1;
  2505.  
  2506.     set_screen_mode(SCREEN_GAME);
  2507.     reset_palette_add();
  2508.  
  2509.     #ifdef ARCADE
  2510.     keys_override = FindArg("-keys");
  2511.     #endif
  2512.  
  2513.     set_warn_func(game_show_warning);
  2514.  
  2515.     init_cockpit();
  2516.     init_gauges();
  2517.     //digi_init_sounds();
  2518.  
  2519.     //keyd_repeat = 0;                // Don't allow repeat in game
  2520.     keyd_repeat = 1;                // Do allow repeat in game
  2521.  
  2522.     //_MARK_("start of game");Commented out -KRB
  2523.  
  2524.     #ifdef EDITOR
  2525.         if (Segments[ConsoleObject->segnum].segnum == -1)      //segment no longer exists
  2526.             obj_relink( ConsoleObject-Objects, SEG_PTR_2_NUM(Cursegp) );
  2527.  
  2528.         if (!check_obj_seg(ConsoleObject))
  2529.             move_player_2_segment(Cursegp,Curside);
  2530.     #endif
  2531.  
  2532.     Viewer = ConsoleObject;
  2533.     fly_init(ConsoleObject);
  2534.  
  2535.     Game_suspended = 0;
  2536.  
  2537.     #ifdef ARCADE
  2538.     if (Arcade_mode)    {
  2539.         NewGame(1);
  2540.         newdemo_start_playback(NULL);
  2541.     }
  2542.     #endif
  2543.  
  2544.     reset_time();
  2545.     FrameTime = 0;          //make first frame zero
  2546.  
  2547.     #ifdef EDITOR
  2548.     if (Current_level_num == 0) {           //not a real level
  2549.         init_player_stats_game();
  2550.         init_ai_objects();
  2551.     }
  2552.     #endif
  2553.  
  2554.     fix_object_segs();
  2555.  
  2556.     game_flush_inputs();
  2557.  
  2558.     if ( setjmp(LeaveGame)==0 ) {
  2559.  
  2560.         if (VR_screen_mode != SCREEN_MENU)
  2561.             vr_reset_display();
  2562.  
  2563.         while (1) {
  2564.             keyboard_update();
  2565.             
  2566.             // GAME LOOP!
  2567.             Automap_flag = 0;
  2568.             Config_menu_flag = 0;
  2569.  
  2570.             Assert( ConsoleObject == &Objects[Players[Player_num].objnum] );
  2571.  
  2572.             GameLoop( 1, 1 );       // Do game loop with rendering and reading controls.
  2573.  
  2574.             if (Config_menu_flag)   {
  2575.                 if (!(Game_mode&GM_MULTI)) palette_save();
  2576.                 do_options_menu();
  2577.                 if (!(Game_mode&GM_MULTI)) palette_restore();       
  2578.             }
  2579.  
  2580.             if (Automap_flag) {
  2581.                 int save_w=Game_window_w,save_h=Game_window_h;
  2582. //                printf("Automap!\n");
  2583.                 do_automap(0);
  2584.                 Screen_mode=-1; set_screen_mode(SCREEN_GAME);
  2585.                 Game_window_w=save_w; Game_window_h=save_h;
  2586.                 init_cockpit();
  2587.                 last_drawn_cockpit[0] = -1;
  2588.                 last_drawn_cockpit[1] = -1;
  2589.  
  2590.                 if (VR_screen_mode != SCREEN_MENU)
  2591.                     vr_reset_display();
  2592.             }
  2593.  
  2594.             if ( (Function_mode != FMODE_GAME) && Auto_demo && (Newdemo_state != ND_STATE_NORMAL) ) {
  2595.                 int choice, fmode;
  2596.                 fmode = Function_mode;
  2597.                 Function_mode = FMODE_GAME;
  2598.                 choice=nm_messagebox( NULL, 2, TXT_YES, TXT_NO, TXT_ABORT_AUTODEMO );
  2599.                 Function_mode = fmode;
  2600.                 if (choice==0)  {
  2601.                     Auto_demo = 0;  
  2602.                     newdemo_stop_playback();
  2603.                     Function_mode = FMODE_MENU;
  2604.                 } else {
  2605.                     Function_mode = FMODE_GAME;
  2606.                 }
  2607.             }
  2608.     
  2609.             if ( (Function_mode != FMODE_GAME ) && (Newdemo_state != ND_STATE_PLAYBACK ) && (Function_mode!=FMODE_EDITOR) )     {
  2610.                 int choice, fmode;
  2611.                 fmode = Function_mode;
  2612.                 Function_mode = FMODE_GAME;
  2613.                 choice=nm_messagebox( NULL, 2, TXT_YES, TXT_NO, TXT_ABORT_GAME );
  2614.                 Function_mode = fmode;
  2615.                 if (choice != 0)
  2616.                     Function_mode = FMODE_GAME;
  2617.             }
  2618.  
  2619.             if (Function_mode != FMODE_GAME)
  2620.                 longjmp(LeaveGame,0);
  2621.         }
  2622.     } 
  2623.  
  2624.     digi_stop_all();
  2625.  
  2626.     if ( (Newdemo_state == ND_STATE_RECORDING) || (Newdemo_state == ND_STATE_PAUSED) )
  2627.         newdemo_stop_recording();
  2628.  
  2629.     #ifdef NETWORK
  2630.     multi_leave_game();
  2631.     #endif
  2632.  
  2633.     if ( Newdemo_state == ND_STATE_PLAYBACK )   
  2634.         newdemo_stop_playback();
  2635.  
  2636.     if (Function_mode != FMODE_EDITOR)
  2637.         gr_palette_fade_out(gr_palette,32,0);           // Fade out before going to menu
  2638.  
  2639.     //@@if ( (!demo_playing) && (!multi_game) && (Function_mode != FMODE_EDITOR) )  {
  2640.     //@@    scores_maybe_add_player(Game_aborted);
  2641.     //@@}
  2642.  
  2643.     //_MARK_("end of game");//Commented out -KRB
  2644.  
  2645.     clear_warn_func(game_show_warning);     //don't use this func anymore
  2646.  
  2647.     game_disable_cheats();
  2648.  
  2649. #ifdef DEBUG_PROFILE
  2650.     profile_full_time += timer_get_fixed_seconds() - start_time;
  2651. #endif
  2652.  
  2653. }
  2654.  
  2655. extern void john_cheat_func_1(int);
  2656. extern void john_cheat_func_2(int);
  2657. extern void john_cheat_func_3(int);
  2658. extern void john_cheat_func_4(int);
  2659.  
  2660. //called at the end of the program
  2661. void close_game() 
  2662. {
  2663.     if (VR_offscreen_buffer)    {
  2664.         gr_free_canvas(VR_offscreen_buffer);            
  2665.         VR_offscreen_buffer = NULL;
  2666.     }
  2667.  
  2668.     close_gauge_canvases();
  2669.  
  2670.     restore_effect_bitmap_icons();
  2671.  
  2672.     if (Game_cockpit_copy_code) {
  2673.         free(Game_cockpit_copy_code);
  2674.         Game_cockpit_copy_code = NULL;
  2675.     }
  2676.  
  2677.     if (background_bitmap.bm_data)
  2678.         free(background_bitmap.bm_data);
  2679.  
  2680.     clear_warn_func(game_show_warning);     //don't use this func anymore
  2681. }
  2682.  
  2683. grs_canvas * get_current_game_screen()
  2684. {
  2685.     return &VR_screen_pages[VR_current_page];
  2686. }
  2687.  
  2688. ubyte exploding_flag = 0;
  2689.  
  2690. extern dump_used_textures_all();
  2691. extern kconfig_center_headset();
  2692.  
  2693. void ReadControls()
  2694. {
  2695.     int key;
  2696.     fix key_time;
  2697.     static fix newdemo_single_frame_time;
  2698.  
  2699.         #ifdef ARCADE
  2700.         if (Arcade_mode)    {
  2701.             int coins;
  2702.             if (Newdemo_state!=ND_STATE_PLAYBACK)   {
  2703.                 Arcade_timer -= 2*FrameTime;
  2704.                 if ( Arcade_timer < (-F1_0*10) )    {
  2705.                     newdemo_toggle_playback();
  2706.                 }
  2707.             }
  2708.             coins = coindev_count(0);
  2709.             if (coins>0)    {
  2710.                 if ( Newdemo_state==ND_STATE_PLAYBACK ) {
  2711.                     newdemo_toggle_playback();
  2712.                     Arcade_timer = F1_0 * ARCADE_FIRST_SECONDS;     // Two minutes to play...
  2713.                     if (coins>1)
  2714.                         Arcade_timer += F1_0 * ARCADE_CONTINUE_SECONDS*(coins-1);       // Two minutes to play...
  2715.                     NewGame(1);
  2716.                 } else {
  2717.                     if (Arcade_timer < 0 )
  2718.                         Arcade_timer = 0;
  2719.                     Arcade_timer += F1_0 * ARCADE_CONTINUE_SECONDS*coins;       // Two minutes to play...
  2720.                 }
  2721.             }
  2722.         }
  2723.         #endif
  2724.  
  2725.         Player_fired_laser_this_frame=-1;
  2726.  
  2727. #ifndef NDEBUG
  2728.         if (Speedtest_on)
  2729.             speedtest_frame();
  2730. #endif
  2731.  
  2732.         if (!Endlevel_sequence && !Player_is_dead) {
  2733.  
  2734.             #ifdef ARCADE
  2735.             if (Arcade_mode)    {
  2736.                 if ( Arcade_timer > 0 )
  2737.                     if (Newdemo_state == ND_STATE_PLAYBACK )
  2738.                         memset( &Controls, 0, sizeof(control_info) );
  2739.                     else
  2740.                         controls_read_all();        //NOTE LINK TO ABOVE!!!
  2741.             } else
  2742.             #endif
  2743.                 if ( (Newdemo_state == ND_STATE_PLAYBACK) 
  2744.                     #ifdef NETWORK
  2745.                     || multi_sending_message || multi_defining_message
  2746.                     #endif
  2747.                     )   // WATCH OUT!!! WEIRD CODE ABOVE!!!
  2748.                     memset( &Controls, 0, sizeof(control_info) );
  2749.                 else
  2750.                     controls_read_all();        //NOTE LINK TO ABOVE!!!
  2751.  
  2752.             check_rear_view();
  2753.                         
  2754.             //  If automap key pressed, enable automap unless you are in network mode, control center destroyed and < 10 seconds left
  2755.             if ( Controls.automap_down_count && !((Game_mode & GM_MULTI) && Fuelcen_control_center_destroyed && (Fuelcen_seconds_left < 10)))
  2756.                 Automap_flag = 1;           
  2757.  
  2758.             if (Controls.fire_flare_down_count)
  2759.                 if (allowed_to_fire_flare())
  2760.                     Flare_create(ConsoleObject);
  2761.  
  2762.             if (allowed_to_fire_missile())
  2763.                 Global_missile_firing_count += Weapon_info[Secondary_weapon_to_weapon_info[Secondary_weapon]].fire_count * (Controls.fire_secondary_state || Controls.fire_secondary_down_count);
  2764.  
  2765.             if (Global_missile_firing_count) {
  2766.                 do_missile_firing();
  2767.                 Global_missile_firing_count--;
  2768.             }
  2769.  
  2770.             if (Global_missile_firing_count < 0)
  2771.                 Global_missile_firing_count = 0;
  2772.  
  2773.             //  Drop proximity bombs.
  2774.             if (Controls.drop_bomb_down_count) {
  2775.                 int ssw_save = Secondary_weapon;
  2776.                 Secondary_weapon = PROXIMITY_INDEX;
  2777.                 while (Controls.drop_bomb_down_count--)
  2778.                     do_missile_firing();
  2779.                 Secondary_weapon = ssw_save;
  2780.             }
  2781.         }
  2782.  
  2783.         if (Player_exploded) { //Player_is_dead && (ConsoleObject->flags & OF_EXPLODING) ) {
  2784.             if (exploding_flag==0)  {
  2785.                 exploding_flag = 1;         // When player starts exploding, clear all input devices...
  2786.                 game_flush_inputs();
  2787.             } else {    
  2788.                 int i;
  2789.                 if (key_down_count(KEY_BACKSP))
  2790.                     Int3();
  2791.                 if (key_down_count(KEY_PRINT_SCREEN))
  2792.                     save_screen_shot(0);
  2793.                 for (i=0; i<4; i++ )    
  2794.                     if (joy_get_button_down_cnt(i)>0) Death_sequence_aborted = 1;
  2795.                 for (i=0; i<3; i++ )    
  2796.                     if (mouse_button_down_count(i)>0) Death_sequence_aborted = 1;
  2797.                 for (i=0; i<256; i++ )  
  2798.                     if (key_down_count(i)>0) Death_sequence_aborted = 1;
  2799.                 if (Death_sequence_aborted)
  2800.                     game_flush_inputs();
  2801.             }
  2802.         } else {
  2803.             exploding_flag=0;
  2804.         }
  2805.  
  2806.         if (Newdemo_state == ND_STATE_PLAYBACK )    {
  2807.             if ((keyd_pressed[KEY_LSHIFT] || keyd_pressed[KEY_RSHIFT]) && keyd_pressed[KEY_RIGHT])
  2808.                 Newdemo_vcr_state = ND_STATE_FASTFORWARD;
  2809.             else if ((keyd_pressed[KEY_LSHIFT] || keyd_pressed[KEY_RSHIFT]) && keyd_pressed[KEY_LEFT])
  2810.                 Newdemo_vcr_state = ND_STATE_REWINDING;
  2811.             else if (!(keyd_pressed[KEY_LCTRL] || keyd_pressed[KEY_RCTRL]) && keyd_pressed[KEY_RIGHT] && ((timer_get_fixed_seconds() - newdemo_single_frame_time) >= F1_0))
  2812.                 Newdemo_vcr_state = ND_STATE_ONEFRAMEFORWARD;
  2813.             else if (!(keyd_pressed[KEY_LCTRL] || keyd_pressed[KEY_RCTRL]) && keyd_pressed[KEY_LEFT] && ((timer_get_fixed_seconds() - newdemo_single_frame_time) >= F1_0))
  2814.                 Newdemo_vcr_state = ND_STATE_ONEFRAMEBACKWARD;
  2815.             else if ((Newdemo_vcr_state == ND_STATE_FASTFORWARD) || (Newdemo_vcr_state == ND_STATE_REWINDING))
  2816.                 Newdemo_vcr_state = ND_STATE_PLAYBACK;
  2817.         }
  2818.  
  2819.         while ((key=key_inkey_time(&key_time)) != 0)    {
  2820.  
  2821.             john_cheat_func_1(key);
  2822.  
  2823.             #ifdef NETWORK
  2824.             if ( (Game_mode&GM_MULTI) && (multi_sending_message || multi_defining_message ))    {
  2825.                 multi_message_input_sub( key );
  2826.                 key = 0;        // Wipe out key!
  2827.             }
  2828.             #endif
  2829.  
  2830.             if (!(Game_mode&GM_MULTI) && key == cheat_enable_keys[cheat_enable_index]) {
  2831.                 if (++cheat_enable_index == CHEAT_ENABLE_LENGTH) {
  2832.                     HUD_init_message(TXT_CHEATS_ENABLED);
  2833.                     digi_play_sample( SOUND_CHEATER, F1_0);
  2834.                     Cheats_enabled = 1;
  2835.                     Players[Player_num].score = 0;
  2836.                 }
  2837.             }
  2838.             else
  2839.                 cheat_enable_index = 0;
  2840.  
  2841.  
  2842.             john_cheat_func_2(key);
  2843.  
  2844. #ifdef FINAL_CHEATS
  2845.         if (Cheats_enabled) {
  2846.             if (!(Game_mode&GM_MULTI) && key == cheat_wowie[cheat_wowie_index]) {
  2847.                 if (++cheat_wowie_index == CHEAT_WOWIE_LENGTH) {
  2848.                     int i;
  2849.  
  2850.                     HUD_init_message(TXT_WOWIE_ZOWIE);
  2851.                     digi_play_sample( SOUND_CHEATER, F1_0);
  2852.  
  2853.                     Players[Player_num].primary_weapon_flags |= 0xff ^ (HAS_PLASMA_FLAG | HAS_FUSION_FLAG);
  2854.                     Players[Player_num].secondary_weapon_flags |= 0xff ^ (HAS_SMART_FLAG | HAS_MEGA_FLAG);
  2855.  
  2856.                     for (i=0; i<3; i++)
  2857.                         Players[Player_num].primary_ammo[i] = Primary_ammo_max[i];
  2858.                     
  2859.                     for (i=0; i<3; i++)
  2860.                         Players[Player_num].secondary_ammo[i] = Secondary_ammo_max[i];
  2861.                     
  2862.                     if (Newdemo_state == ND_STATE_RECORDING)
  2863.                         newdemo_record_laser_level(Players[Player_num].laser_level, MAX_LASER_LEVEL);
  2864.  
  2865.                     Players[Player_num].energy = MAX_ENERGY;
  2866.                     Players[Player_num].laser_level = MAX_LASER_LEVEL;
  2867.                     Players[Player_num].flags |= PLAYER_FLAGS_QUAD_LASERS;
  2868.                     update_laser_weapon_info();
  2869.  
  2870.                     cheat_wowie_index = 0;
  2871.                 }
  2872.             }
  2873.             else
  2874.                 cheat_wowie_index = 0;
  2875.  
  2876.             if (!(Game_mode&GM_MULTI) && key == (0xaa^new_cheats[cheat_wowie2_index*NUM_NEW_CHEATS+CHEAT_WOWIE2_OFS])) {
  2877.                 if (++cheat_wowie2_index == CHEAT_WOWIE2_LENGTH) {
  2878.                     int i;
  2879.  
  2880.                     HUD_init_message("SUPER %s",TXT_WOWIE_ZOWIE);
  2881.                     digi_play_sample( SOUND_CHEATER, F1_0);
  2882.  
  2883.                     Players[Player_num].primary_weapon_flags = 0xff;
  2884.                     Players[Player_num].secondary_weapon_flags = 0xff;
  2885.  
  2886.                     for (i=0; i<MAX_PRIMARY_WEAPONS; i++)
  2887.                         Players[Player_num].primary_ammo[i] = Primary_ammo_max[i];
  2888.                     
  2889.                     for (i=0; i<MAX_SECONDARY_WEAPONS; i++)
  2890.                         Players[Player_num].secondary_ammo[i] = Secondary_ammo_max[i];
  2891.                     
  2892.                     if (Newdemo_state == ND_STATE_RECORDING)
  2893.                         newdemo_record_laser_level(Players[Player_num].laser_level, MAX_LASER_LEVEL);
  2894.  
  2895.                     Players[Player_num].energy = MAX_ENERGY;
  2896.                     Players[Player_num].laser_level = MAX_LASER_LEVEL;
  2897.                     Players[Player_num].flags |= PLAYER_FLAGS_QUAD_LASERS;
  2898.                     update_laser_weapon_info();
  2899.  
  2900.                     cheat_wowie2_index = 0;
  2901.                 }
  2902.             }
  2903.             else
  2904.                 cheat_wowie2_index = 0;
  2905.  
  2906.             if (!(Game_mode&GM_MULTI) && key == cheat_allkeys[cheat_allkeys_index]) {
  2907.                 if (++cheat_allkeys_index == CHEAT_ALLKEYS_LENGTH) {
  2908.                     HUD_init_message(TXT_ALL_KEYS);
  2909.                     digi_play_sample( SOUND_CHEATER, F1_0);
  2910.                     Players[Player_num].flags |= PLAYER_FLAGS_BLUE_KEY | PLAYER_FLAGS_RED_KEY | PLAYER_FLAGS_GOLD_KEY;
  2911.  
  2912.                     cheat_allkeys_index = 0;
  2913.                 }
  2914.             }
  2915.             else
  2916.                 cheat_allkeys_index = 0;
  2917.  
  2918.  
  2919.             if (!(Game_mode&GM_MULTI) && key == cheat_invuln[cheat_invuln_index]) {
  2920.                 if (++cheat_invuln_index == CHEAT_INVULN_LENGTH) {
  2921.                     Players[Player_num].flags ^= PLAYER_FLAGS_INVULNERABLE;
  2922.                     HUD_init_message("%s %s!", TXT_INVULNERABILITY, (Players[Player_num].flags&PLAYER_FLAGS_INVULNERABLE)?TXT_ON:TXT_OFF);
  2923.                     digi_play_sample( SOUND_CHEATER, F1_0);
  2924.                     Players[Player_num].invulnerable_time = GameTime+i2f(1000);
  2925.  
  2926.                     cheat_invuln_index = 0;
  2927.                 }
  2928.             }
  2929.             else
  2930.                 cheat_invuln_index = 0;
  2931.  
  2932.             if (!(Game_mode&GM_MULTI) && key == cheat_cloak[cheat_cloak_index]) {
  2933.                 if (++cheat_cloak_index == CHEAT_CLOAK_LENGTH) {
  2934.                     Players[Player_num].flags ^= PLAYER_FLAGS_CLOAKED;
  2935.                     HUD_init_message("%s %s!", TXT_CLOAK, (Players[Player_num].flags&PLAYER_FLAGS_CLOAKED)?TXT_ON:TXT_OFF);
  2936.                     digi_play_sample( SOUND_CHEATER, F1_0);
  2937.                     if (Players[Player_num].flags & PLAYER_FLAGS_CLOAKED) {
  2938.                         ai_do_cloak_stuff();
  2939.                         Players[Player_num].cloak_time = GameTime;
  2940.                     }
  2941.  
  2942.                     cheat_cloak_index = 0;
  2943.                 }
  2944.             }
  2945.             else
  2946.                 cheat_cloak_index = 0;
  2947.  
  2948.             if (!(Game_mode&GM_MULTI) && key == cheat_shield[cheat_shield_index]) {
  2949.                 if (++cheat_shield_index == CHEAT_SHIELD_LENGTH) {
  2950.                     HUD_init_message(TXT_FULL_SHIELDS);
  2951.                     digi_play_sample( SOUND_CHEATER, F1_0);
  2952.                     Players[Player_num].shields = MAX_SHIELDS;
  2953.  
  2954.                     cheat_shield_index = 0;
  2955.                 }
  2956.             }
  2957.             else
  2958.                 cheat_shield_index = 0;
  2959.  
  2960.             if (!(Game_mode&GM_MULTI) && key == cheat_warp[cheat_warp_index]) {
  2961.                 if (++cheat_warp_index == CHEAT_WARP_LENGTH) {
  2962.                     newmenu_item m;
  2963.                     char text[10]="";
  2964.                     int new_level_num;
  2965.                     int item;
  2966.                     digi_play_sample( SOUND_CHEATER, F1_0);
  2967.                     m.type=NM_TYPE_INPUT; m.text_len = 10; m.text = text;
  2968.                     item = newmenu_do( NULL, TXT_WARP_TO_LEVEL, 1, &m, NULL );
  2969.                     if (item != -1) {
  2970.                         new_level_num = atoi(m.text);
  2971.                         if (new_level_num!=0 && new_level_num>=0 && new_level_num<=Last_level)
  2972.                             StartNewLevel(new_level_num);
  2973.                     }
  2974.  
  2975.                     cheat_warp_index = 0;
  2976.                 }
  2977.             }
  2978.             else
  2979.                 cheat_warp_index = 0;
  2980.  
  2981.             if (!(Game_mode&GM_MULTI) && key == cheat_astral[cheat_astral_index]) {
  2982.                 if (++cheat_astral_index == CHEAT_ASTRAL_LENGTH) {
  2983.                     digi_play_sample( SOUND_CHEATER, F1_0);
  2984.                     if ( Physics_cheat_flag==0xBADA55 ) {
  2985.                         Physics_cheat_flag = 0;
  2986.                     } else {
  2987.                         Physics_cheat_flag = 0xBADA55;
  2988.                     }
  2989.                     HUD_init_message("%s %s!", "Ghosty mode", Physics_cheat_flag==0xBADA55?TXT_ON:TXT_OFF);
  2990.                     cheat_astral_index = 0;
  2991.                 }
  2992.             }
  2993.             else
  2994.                 cheat_astral_index = 0;
  2995.  
  2996.             if (!(Game_mode&GM_MULTI) && key == (0xaa^new_cheats[cheat_turbomode_index*NUM_NEW_CHEATS+CHEAT_TURBOMODE_OFS])) {
  2997.                 if (++cheat_turbomode_index == CHEAT_TURBOMODE_LENGTH) {
  2998.                     Game_turbo_mode ^= 1;
  2999.                     HUD_init_message("%s %s!", "Turbo mode", Game_turbo_mode?TXT_ON:TXT_OFF);
  3000.                     digi_play_sample( SOUND_CHEATER, F1_0);
  3001.                 }
  3002.             }
  3003.             else
  3004.                 cheat_turbomode_index = 0;
  3005.  
  3006.             if (!(Game_mode&GM_MULTI) && key == (0xaa^new_cheats[cheat_newlife_index*NUM_NEW_CHEATS+CHEAT_NEWLIFE_OFS])) {
  3007.                 if (++cheat_newlife_index == CHEAT_NEWLIFE_LENGTH) {
  3008.                     if (Players[Player_num].lives<50) {
  3009.                         Players[Player_num].lives++;
  3010.                         HUD_init_message("Extra life!");
  3011.                         digi_play_sample( SOUND_CHEATER, F1_0);
  3012.                     }
  3013.  
  3014.                     cheat_newlife_index = 0;
  3015.                 }
  3016.             }
  3017.             else
  3018.                 cheat_newlife_index = 0;
  3019.  
  3020.             if (!(Game_mode&GM_MULTI) && key == (0xaa^new_cheats[cheat_exitpath_index*NUM_NEW_CHEATS+CHEAT_EXITPATH_OFS])) {
  3021.                 if (++cheat_exitpath_index == CHEAT_EXITPATH_LENGTH) {
  3022.                     #ifdef SHOW_EXIT_PATH
  3023.                     if (create_special_path()) {
  3024.                         HUD_init_message("Exit path illuminated!");
  3025.                         digi_play_sample( SOUND_CHEATER, F1_0);
  3026.                     }
  3027.                     #endif
  3028.  
  3029.                     cheat_exitpath_index = 0;
  3030.                 }
  3031.             }
  3032.             else
  3033.                 cheat_exitpath_index = 0;
  3034.  
  3035.  
  3036.             if (!(Game_mode&GM_MULTI) && key == (0xaa^new_cheats[cheat_robotpause_index*NUM_NEW_CHEATS+CHEAT_ROBOTPAUSE_OFS])) {
  3037.                 if (++cheat_robotpause_index == CHEAT_ROBOTPAUSE_LENGTH) {
  3038.                     Robot_firing_enabled = !Robot_firing_enabled;
  3039.                     HUD_init_message("%s %s!", "Robot firing", Robot_firing_enabled?TXT_ON:TXT_OFF);
  3040.                     digi_play_sample( SOUND_CHEATER, F1_0);
  3041.  
  3042.                     cheat_robotpause_index = 0;
  3043.                 }
  3044.  
  3045.             }
  3046.             else
  3047.                 cheat_robotpause_index = 0;
  3048.  
  3049.  
  3050.         }
  3051. #endif
  3052.  
  3053.             john_cheat_func_3(key);
  3054.  
  3055.             #ifndef RELEASE
  3056.             #ifdef NETWORK
  3057.             if ((key&KEY_DEBUGGED)&&(Game_mode&GM_MULTI))   {
  3058.                 Network_message_reciever = 100;     // Send to everyone...
  3059.                 sprintf( Network_message, "%s %s", TXT_I_AM_A, TXT_CHEATER);
  3060.             }
  3061.             #endif
  3062.             #endif
  3063.     
  3064.             if (Endlevel_sequence) {
  3065.  
  3066.                 if (key==KEY_PRINT_SCREEN)
  3067.                     save_screen_shot(0);
  3068.  
  3069.                 if (key == KEY_PAUSE)
  3070.                     key = do_game_pause(0);     //so esc from pause will end level
  3071.  
  3072.                 if (key == KEY_ESC) {
  3073.                     stop_endlevel_sequence();
  3074.                     last_drawn_cockpit[0]=-1;
  3075.                     last_drawn_cockpit[1]=-1;
  3076.                     return;
  3077.                 }
  3078.  
  3079.                 if (key == KEY_BACKSP)
  3080.                     Int3();
  3081.  
  3082.                 break;      //don't process any other keys
  3083.             }
  3084.  
  3085.             john_cheat_func_4(key);
  3086.  
  3087.             if (Player_is_dead) {
  3088.  
  3089.                 if (key==KEY_PRINT_SCREEN)
  3090.                     save_screen_shot(0);
  3091.  
  3092.                 if (key == KEY_PAUSE)   {
  3093.                     key = do_game_pause(0);     //so esc from pause will end level
  3094.                     Death_sequence_aborted  = 0;        // Clear because code above sets this for any key.
  3095.                 }
  3096.                     
  3097.                 if (key == KEY_ESC) {
  3098.                     if (ConsoleObject->flags & OF_EXPLODING)    
  3099.                         Death_sequence_aborted = 1;
  3100.                 }
  3101.  
  3102.                 if (key == KEY_BACKSP)  {
  3103.                     Death_sequence_aborted  = 0;        // Clear because code above sets this for any key.
  3104.                     Int3();
  3105.                 }
  3106.  
  3107.                 break;      //don't process any other keys
  3108.             }
  3109.  
  3110.             if (Newdemo_state == ND_STATE_PLAYBACK )    {
  3111.                 switch (key) {
  3112.  
  3113.                 case KEY_DEBUGGED + KEY_I:  
  3114.                     Newdemo_do_interpolate = !Newdemo_do_interpolate;
  3115.                     if (Newdemo_do_interpolate)
  3116.                         mprintf ((0, "demo playback interpolation now on\n"));
  3117.                     else
  3118.                         mprintf ((0, "demo playback interpolation now off\n"));
  3119.                     break;
  3120. #ifndef NDEBUG
  3121.                 case KEY_DEBUGGED + KEY_K: {
  3122.                     int how_many, c;
  3123.                     char filename[13], num[16];
  3124.                     newmenu_item m[6];
  3125.  
  3126.                     filename[0] = '\0';
  3127.                     m[ 0].type = NM_TYPE_TEXT; m[ 0].text = "output file name";
  3128.                     m[ 1].type = NM_TYPE_INPUT;m[ 1].text_len = 8; m[1].text = filename;
  3129.                     c = newmenu_do( NULL, NULL, 2, m, NULL );
  3130.                     if (c == -2)
  3131.                         break;
  3132.                     strcat(filename, ".dem");
  3133.                     num[0] = '\0';
  3134.                     m[ 0].type = NM_TYPE_TEXT; m[ 0].text = "strip how many bytes";
  3135.                     m[ 1].type = NM_TYPE_INPUT;m[ 1].text_len = 16; m[1].text = num;
  3136.                     c = newmenu_do( NULL, NULL, 2, m, NULL );
  3137.                     if (c == -2)
  3138.                         break;
  3139.                     how_many = atoi(num);
  3140.                     if (how_many <= 0)
  3141.                         break;
  3142.                     newdemo_strip_frames(filename, how_many);
  3143.                 }
  3144.                 break;
  3145. #endif
  3146.  
  3147.                 case KEY_F3:                toggle_cockpit();           break;
  3148.                 case KEY_SHIFTED+KEY_MINUS:
  3149.                 case KEY_MINUS:         shrink_window();            break;
  3150.                 case KEY_SHIFTED+KEY_EQUAL:
  3151.                 case KEY_EQUAL:         grow_window();              break;
  3152.                 case KEY_F2:                Config_menu_flag = 1;   break;
  3153.                 case KEY_F7:                
  3154.                     #ifdef NETWORK
  3155.                     Show_kill_list = (Show_kill_list+1) % ((Newdemo_game_mode & GM_TEAM) ? 3 : 2);
  3156.                     #endif
  3157.                     break;
  3158.                 case KEY_BACKSP:
  3159.                     Int3();
  3160.                     break;
  3161.                 case KEY_ESC:               
  3162.                     Function_mode = FMODE_MENU;
  3163.                     break;
  3164.                 case KEY_UP:
  3165.                     Newdemo_vcr_state = ND_STATE_PLAYBACK;
  3166.                     break;
  3167.                 case KEY_DOWN:
  3168.                     Newdemo_vcr_state = ND_STATE_PAUSED;
  3169.                     break;
  3170.                 case KEY_LEFT:
  3171.                     newdemo_single_frame_time = timer_get_fixed_seconds();
  3172.                     Newdemo_vcr_state = ND_STATE_ONEFRAMEBACKWARD;
  3173.                     break;
  3174.                 case KEY_RIGHT:
  3175.                     newdemo_single_frame_time = timer_get_fixed_seconds();
  3176.                     Newdemo_vcr_state = ND_STATE_ONEFRAMEFORWARD;
  3177.                     break;
  3178.                 case KEY_CTRLED + KEY_RIGHT:
  3179.                     newdemo_goto_end();
  3180.                     break;
  3181.                 case KEY_CTRLED + KEY_LEFT:
  3182.                     newdemo_goto_beginning();
  3183.                     break;
  3184.                 case KEY_PAUSE:
  3185.                     do_game_pause(0);
  3186.                     break;
  3187.                 case KEY_PRINT_SCREEN: {
  3188.                     int old_state;
  3189.             
  3190.                     old_state = Newdemo_vcr_state;
  3191.                     Newdemo_vcr_state = ND_STATE_PRINTSCREEN;
  3192.                     game_render_frame_mono();
  3193.                     save_screen_shot(0);
  3194.                     Newdemo_vcr_state = old_state;
  3195.                     break;
  3196.                     }
  3197.                 }
  3198.                 break;
  3199.             }
  3200.  
  3201.  
  3202. #ifndef FINAL_CHEATS
  3203.             //Here are the "legal" cheats
  3204.             if (Cheats_enabled && !(Game_mode&GM_MULTI))
  3205.                 switch (key) {
  3206.                     case KEY_ALTED+KEY_1: {
  3207.                         int i;
  3208.  
  3209.                         HUD_init_message(TXT_WOWIE_ZOWIE);
  3210.  
  3211.                         if (UseShareware) {
  3212.                             Players[Player_num].primary_weapon_flags = 0xff;
  3213.                             Players[Player_num].secondary_weapon_flags = 0xff;
  3214.                         } else {
  3215.                             Players[Player_num].primary_weapon_flags = 0xff ^ (HAS_PLASMA_FLAG | HAS_FUSION_FLAG);
  3216.                             Players[Player_num].secondary_weapon_flags = 0xff ^ (HAS_SMART_FLAG | HAS_MEGA_FLAG);
  3217.                         }
  3218.  
  3219.                         for (i=0; i<MAX_PRIMARY_WEAPONS; i++)
  3220.                             Players[Player_num].primary_ammo[i] = Primary_ammo_max[i];
  3221.                         
  3222.                         for (i=0; i<MAX_SECONDARY_WEAPONS; i++)
  3223.                             Players[Player_num].secondary_ammo[i] = Secondary_ammo_max[i];
  3224.                         
  3225.                         if (Newdemo_state == ND_STATE_RECORDING)
  3226.                             newdemo_record_laser_level(Players[Player_num].laser_level, MAX_LASER_LEVEL);
  3227.  
  3228.                         Players[Player_num].energy = MAX_ENERGY;
  3229.                         Players[Player_num].laser_level = MAX_LASER_LEVEL;
  3230.                         Players[Player_num].flags |= PLAYER_FLAGS_QUAD_LASERS;
  3231.                         update_laser_weapon_info();
  3232.  
  3233.                         break;
  3234.                     }
  3235.     
  3236.                     case KEY_ALTED+KEY_2:
  3237.                         HUD_init_message(TXT_ALL_KEYS);
  3238.                         Players[Player_num].flags |= PLAYER_FLAGS_BLUE_KEY | PLAYER_FLAGS_RED_KEY | PLAYER_FLAGS_GOLD_KEY;
  3239.                         break;
  3240.     
  3241.                     case KEY_ALTED+KEY_3:
  3242.                         Players[Player_num].flags ^= PLAYER_FLAGS_INVULNERABLE;
  3243.                         HUD_init_message("%s %s!", TXT_INVULNERABILITY, (Players[Player_num].flags&PLAYER_FLAGS_INVULNERABLE)?TXT_ON:TXT_OFF);
  3244.                         Players[Player_num].invulnerable_time = GameTime+i2f(1000);
  3245.                         break;
  3246.     
  3247.                     case KEY_ALTED+KEY_4:
  3248.                         Players[Player_num].flags ^= PLAYER_FLAGS_CLOAKED;
  3249.                         HUD_init_message("%s %s!", TXT_CLOAK, (Players[Player_num].flags&PLAYER_FLAGS_CLOAKED)?TXT_ON:TXT_OFF);
  3250.                         if (Players[Player_num].flags & PLAYER_FLAGS_CLOAKED) {
  3251.                             ai_do_cloak_stuff();
  3252.                             Players[Player_num].cloak_time = GameTime;
  3253.                         }
  3254.                         break;
  3255.  
  3256.                     case KEY_ALTED+KEY_5:
  3257.                         HUD_init_message(TXT_FULL_SHIELDS);
  3258.                         Players[Player_num].shields = MAX_SHIELDS;
  3259.                         break;
  3260.  
  3261.                     case KEY_ALTED+KEY_6: {
  3262.                         newmenu_item m;
  3263.                         char text[10]="";
  3264.                         int new_level_num;
  3265.                         int item;
  3266.                         m.type=NM_TYPE_INPUT; m.text_len = 10; m.text = text;
  3267.                         item = newmenu_do( NULL, TXT_WARP_TO_LEVEL, 1, &m, NULL );
  3268.                         if (item != -1) {
  3269.                             new_level_num = atoi(m.text);
  3270.                             if (new_level_num!=0 && new_level_num>=0 && new_level_num<=LAST_LEVEL)
  3271.                                 StartNewLevel(new_level_num);
  3272.                         }
  3273.                         break;
  3274.  
  3275.                     }
  3276.                 }
  3277. #endif
  3278.  
  3279.             //--killed--Players[Player_num].flags &= ~PLAYER_FLAGS_AFTERBURNER; //  Turn off, keypress might turn it on.
  3280.  
  3281.             switch (key) {
  3282.  
  3283.                 //  ================================================================================================
  3284.                 //FIRST ARE ALL THE REAL GAME KEYS.  PUT TEST AND DEBUG KEYS LATER.
  3285.  
  3286.                 //--killed--case KEY_SHIFTED+KEY_A: toggle_afterburner_status();    break;
  3287.                 case KEY_ESC:
  3288.                     Game_aborted=1;
  3289.                     Function_mode = FMODE_MENU;
  3290.                     break;
  3291.                 case KEY_F1:                do_show_help();         break;
  3292. #ifdef VIRGIN
  3293.                 case KEY_ALTED+KEY_F1:
  3294.                     do_virge_menu();
  3295.                     break;
  3296. #endif
  3297. #ifdef WARP3D
  3298.                 case KEY_ALTED+KEY_F1:
  3299.                     do_warp_menu();
  3300.                     break;
  3301. #endif
  3302.                 case KEY_F2:                Config_menu_flag = 1;   break;
  3303.                 case KEY_F3:                toggle_cockpit();           break;
  3304.                 case KEY_F4:                palette_save(); joydefs_calibrate(); palette_restore(); break;
  3305.                 case KEY_F5:    
  3306.                         if ( Newdemo_state == ND_STATE_RECORDING )
  3307.                             newdemo_stop_recording();
  3308.                         else if ( Newdemo_state == ND_STATE_NORMAL )            
  3309.                             newdemo_start_recording();
  3310.                         break;
  3311.                 case KEY_F6:                
  3312.                     #ifdef NETWORK
  3313.                     Show_reticle_name = (Show_reticle_name+1)%2;
  3314.                     #endif
  3315.                     break;  
  3316.                 case KEY_F7:                
  3317.                     #ifdef NETWORK
  3318.                     Show_kill_list = (Show_kill_list+1) % ((Game_mode & GM_TEAM) ? 3 : 2);
  3319.                     #endif
  3320.                     break;
  3321.                 case KEY_F8:    
  3322.                     #ifdef NETWORK
  3323.                     multi_send_message_start();
  3324.                     #endif
  3325.                     break;
  3326.                 case KEY_F9:
  3327.                 case KEY_F10:
  3328.                 case KEY_F11:
  3329.                 case KEY_F12:
  3330.                     #ifdef NETWORK
  3331.                     multi_send_macro(key);
  3332.                     #endif
  3333.                     break;      // send taunt macros
  3334.     
  3335.                 case KEY_ALTED + KEY_F9:
  3336.                 case KEY_CTRLED + KEY_F9:
  3337.                     #ifdef NETWORK
  3338.                     multi_send_audio_taunt(0);
  3339.                     #endif
  3340.                     break;
  3341.                 case KEY_ALTED + KEY_F10:
  3342.                 case KEY_CTRLED + KEY_F10:
  3343.                     #ifdef NETWORK
  3344.                     multi_send_audio_taunt(1);
  3345.                     #endif
  3346.                     break;
  3347.                 case KEY_ALTED + KEY_F11:
  3348.                 case KEY_CTRLED + KEY_F11:
  3349.                     #ifdef NETWORK
  3350.                     multi_send_audio_taunt(2);
  3351.                     #endif
  3352.                     break;
  3353.                 case KEY_ALTED + KEY_F12:
  3354.                 case KEY_CTRLED + KEY_F12:
  3355.                     #ifdef NETWORK
  3356.                     multi_send_audio_taunt(3);
  3357.                     #endif
  3358.                     break;
  3359.  
  3360.                 case KEY_SHIFTED + KEY_F9:
  3361.                 case KEY_SHIFTED + KEY_F10:
  3362.                 case KEY_SHIFTED + KEY_F11:
  3363.                 case KEY_SHIFTED + KEY_F12:
  3364.                     #ifdef NETWORK
  3365.                     multi_define_macro(key);
  3366.                     #endif
  3367.                     break;      // redefine taunt macros
  3368.  
  3369.                 case KEY_PAUSE:         do_game_pause(1);       break;
  3370.                 case KEY_PRINT_SCREEN:  save_screen_shot(0);        break;
  3371.  
  3372.                 case KEY_SHIFTED+KEY_MINUS:
  3373.                 case KEY_MINUS:         shrink_window();            break;
  3374.                 case KEY_SHIFTED+KEY_EQUAL:
  3375.                 case KEY_EQUAL:         grow_window();              break;
  3376.  
  3377.                 //  Select primary or secondary weapon.
  3378.                 case KEY_1:
  3379.                 case KEY_2:
  3380.                 case KEY_3:
  3381.                 case KEY_4:
  3382.                 case KEY_5:
  3383.  
  3384.                     do_weapon_select(key - KEY_1 , 0);
  3385.                     break;
  3386.  
  3387.                 case KEY_6:
  3388.                 case KEY_7:
  3389.                 case KEY_8:
  3390.                 case KEY_9:
  3391.                 case KEY_0:
  3392.  
  3393.                     do_weapon_select(key - KEY_6 , 1);
  3394.                     break;
  3395.  
  3396.                 case KEY_SHIFTED + KEY_ESC: //quick exit
  3397.                     #ifdef EDITOR
  3398.                         if (! SafetyCheck()) break;
  3399.                         close_editor_screen();
  3400.                     #endif
  3401.  
  3402.                     Game_aborted=1;
  3403.                     Function_mode=FMODE_EXIT;
  3404.                     break;
  3405.  
  3406. #ifdef SHAREWARE
  3407.                 case KEY_ALTED+KEY_F2:
  3408.                 case KEY_CTRLED+KEY_F2:
  3409.                 case KEY_ALTED+KEY_F3:
  3410.                 case KEY_CTRLED+KEY_F3:
  3411.                     HUD_init_message( TXT_ONLY_REGISTERED );
  3412.                     digi_play_sample( SOUND_BAD_SELECTION, F1_0 );
  3413.                     break;
  3414. #else
  3415.                 case KEY_ALTED+KEY_F2:  state_save_all( 0 );        break;  // 0 means not between levels.
  3416.                 case KEY_CTRLED+KEY_F2: state_save_all( 0 );        break;  // 0 means not between levels.
  3417.                 case KEY_CTRLED+KEY_F3: state_restore_all(1);       break;
  3418.                 case KEY_ALTED+KEY_F3:  state_restore_all(1);       break;
  3419. #endif
  3420.  
  3421.                 case KEY_SHIFTED+KEY_Z:
  3422.                     kconfig_center_headset();
  3423.                     break;
  3424.  
  3425.  
  3426.                 case KEY_V + KEY_ALTED:     // changes 11/9/95
  3427.                     if ( Game_victor_flag )     {
  3428.                         victor_init_graphics();
  3429.                         HUD_init_message( "Victor mode toggled" );
  3430.                     }
  3431.                     break;
  3432.  
  3433.                     // changes 11/9/95, 11/10/95
  3434.                 case KEY_SHIFTED+KEY_F5:  
  3435.                     if ( Game_victor_flag )     {
  3436.                         victor_init_graphics();
  3437.                         HUD_init_message( "Victor mode toggled" );
  3438.                     } else if ( VR_render_mode != VR_NONE ) {
  3439.                         simuleyes_offset_ratio = VR_DEFAULT_OFFSET_RATIO;
  3440.                         simuleyes_adjusted_offset_ratio = fixdiv (simuleyes_offset_ratio *
  3441.                                 VR_PIXEL_SHIFT, VR_SEPARATION);
  3442.                         VR_eye_width        = VR_SEPARATION;
  3443.                         VR_eye_offset = VR_PIXEL_SHIFT;
  3444.                         VR_eye_offset_changed = 2;
  3445.                         HUD_init_message( "Stereo parameters reset");
  3446.                     }
  3447.                     break;
  3448.  
  3449.                 case KEY_SHIFTED+KEY_F6:
  3450.                         if ( VR_render_mode != VR_NONE )    {
  3451.                             if (Game_simuleyes_flag)    {
  3452.                                 vr_reset_display();
  3453.                             } else {
  3454.                                 VR_low_res++;
  3455.                                 if ( VR_low_res > 3 ) VR_low_res = 0;
  3456.                                 switch( VR_low_res )    {
  3457.                                     case 0: HUD_init_message( "High Res" ); break;
  3458.                                     case 1: HUD_init_message( "Low V.Res" ); break;
  3459.                                     case 2: HUD_init_message( "Low H.Res" ); break;
  3460.                                     case 3: HUD_init_message( "Low Res" ); break;
  3461.                                 }
  3462.                             }
  3463.                         }
  3464.                     break;
  3465.  
  3466.                 case KEY_SHIFTED+KEY_F7:
  3467.                     if (!Game_simuleyes_flag)   {  // constraint added
  3468.                         if ( VR_render_mode != VR_NONE )    {
  3469.                             VR_switch_eyes = !VR_switch_eyes;
  3470.                             if ( VR_switch_eyes )
  3471.                                 HUD_init_message( "Right Eye -- Left Eye" );
  3472.                             else
  3473.                                 HUD_init_message( "Left Eye -- Right Eye" );
  3474.                         }
  3475.                     }
  3476.                     break;
  3477.  
  3478.                 case KEY_SHIFTED+KEY_F8:
  3479.                     if (!Game_simuleyes_flag)   {  // constraint added
  3480.                         VR_sensitivity++;
  3481.                         if (VR_sensitivity > 2 )
  3482.                             VR_sensitivity = 0;
  3483.                         HUD_init_message( "Head tracking sensitivy = %d", VR_sensitivity );
  3484.                     }
  3485.                     break;
  3486.  
  3487.                 case KEY_SHIFTED+KEY_ENTER:
  3488.                     if ( VR_render_mode != VR_NONE )    {
  3489.                         VR_show_hud = !VR_show_hud;
  3490.                     }
  3491.                     break;
  3492.  
  3493.                 case KEY_SHIFTED+KEY_F1:   // altered 11/9/95, 11/10/95
  3494.                         simuleyes_offset_ratio = fixdiv (simuleyes_offset_ratio,
  3495.                                 VR_ADJUST_OFFSET_RATIO);
  3496.                         if (simuleyes_offset_ratio <    VR_MIN_OFFSET_RATIO)
  3497.                             simuleyes_offset_ratio = VR_MIN_OFFSET_RATIO;
  3498.                         simuleyes_adjusted_offset_ratio = fixdiv (simuleyes_offset_ratio *
  3499.                                 VR_PIXEL_SHIFT, VR_SEPARATION);
  3500.                         VR_eye_offset = (int) ((fixmul (simuleyes_adjusted_offset_ratio,
  3501.                                 VR_eye_width) - F1_0/2) / F1_0);
  3502.                         HUD_init_message( "Stereoscopic balance = %.1f",
  3503.                                 f2fl(simuleyes_offset_ratio)*10);
  3504.                     VR_eye_offset_changed = 2;
  3505.                     break;
  3506.                 case KEY_SHIFTED+KEY_F2:   // altered 11/9/95, 11/10/95
  3507.                         simuleyes_offset_ratio = fixmul (simuleyes_offset_ratio,
  3508.                                 VR_ADJUST_OFFSET_RATIO);
  3509.                         if (simuleyes_offset_ratio > VR_MAX_OFFSET_RATIO)
  3510.                             simuleyes_offset_ratio = VR_MAX_OFFSET_RATIO;
  3511.                         simuleyes_adjusted_offset_ratio = fixdiv (simuleyes_offset_ratio *
  3512.                                 VR_PIXEL_SHIFT, VR_SEPARATION);
  3513.                         VR_eye_offset = (int) ((fixmul (simuleyes_adjusted_offset_ratio,
  3514.                                 VR_eye_width) - F1_0/2) / F1_0);
  3515.                         HUD_init_message( "Stereoscopic balance = %.1f",
  3516.                                 f2fl(simuleyes_offset_ratio)*10);
  3517.                     VR_eye_offset_changed = 2;
  3518.                     break;
  3519.                 case KEY_SHIFTED+KEY_F3:
  3520.                         VR_eye_width = VR_eye_width * 10 / 11;
  3521.                         if ( VR_eye_width < VR_MIN_SEPARATION )
  3522.                             VR_eye_width = VR_MIN_SEPARATION;
  3523.                         VR_eye_offset = (int) ((fixmul (simuleyes_adjusted_offset_ratio,
  3524.                                 VR_eye_width) - F1_0/2) / F1_0);
  3525.                         VR_eye_offset_changed = 2;
  3526.                         HUD_init_message( "Stereo separation = %.1f", f2fl(VR_eye_width)*10);
  3527.                     break;
  3528.                 case KEY_SHIFTED+KEY_F4:
  3529.                         VR_eye_width = VR_eye_width * 11 / 10;
  3530.                         if ( VR_eye_width > VR_MAX_SEPARATION )
  3531.                             VR_eye_width = VR_MAX_SEPARATION; //11/10/95
  3532.                         VR_eye_offset = (int) ((fixmul (simuleyes_adjusted_offset_ratio,
  3533.                                 VR_eye_width) - F1_0/2) / F1_0);
  3534.                         VR_eye_offset_changed = 2;
  3535.                         HUD_init_message( "Stereo separation = %.1f", f2fl(VR_eye_width)*10);
  3536.                     break;
  3537.  
  3538.  
  3539.  
  3540.                 //use function keys for window sizing
  3541.  
  3542.                 //  ================================================================================================
  3543.                 //ALL KEYS BELOW HERE GO AWAY IN RELEASE VERSION
  3544.  
  3545.             #ifndef RELEASE
  3546.     
  3547.                 case KEY_DEBUGGED+KEY_0:    show_weapon_status();   break;
  3548.  
  3549.                 #ifdef SHOW_EXIT_PATH
  3550.                 case KEY_DEBUGGED+KEY_1:    create_special_path();  break;
  3551.                 #endif
  3552.  
  3553.                 case KEY_DEBUGGED+KEY_Y:
  3554.                     do_controlcen_destroyed_stuff(NULL);
  3555.                     break;
  3556.  
  3557.                 case KEY_BACKSP:
  3558.                 case KEY_CTRLED+KEY_BACKSP:
  3559.                 case KEY_ALTED+KEY_BACKSP:
  3560.                 case KEY_SHIFTED+KEY_BACKSP:
  3561.                 case KEY_SHIFTED+KEY_ALTED+KEY_BACKSP:
  3562.                 case KEY_CTRLED+KEY_ALTED+KEY_BACKSP:
  3563.                 case KEY_SHIFTED+KEY_CTRLED+KEY_BACKSP:
  3564.                 case KEY_SHIFTED+KEY_CTRLED+KEY_ALTED+KEY_BACKSP:
  3565.  
  3566.                         Int3(); break;
  3567.  
  3568.                 case KEY_DEBUGGED+KEY_S:            digi_reset(); break;
  3569.  
  3570.                 case KEY_DEBUGGED+KEY_P:
  3571.                     if (Game_suspended & SUSP_ROBOTS)
  3572.                         Game_suspended &= ~SUSP_ROBOTS;         //robots move
  3573.                     else
  3574.                         Game_suspended |= SUSP_ROBOTS;          //robots don't move
  3575.                     break;
  3576.     
  3577.  
  3578.     
  3579.                 case KEY_DEBUGGED+KEY_K:    Players[Player_num].shields = 1;    break;                      //  a virtual kill
  3580.                 case KEY_DEBUGGED+KEY_SHIFTED + KEY_K:  Players[Player_num].shields = -1;   break;  //  an actual kill
  3581.                 case KEY_DEBUGGED+KEY_X: Players[Player_num].lives++; break; // Extra life cheat key.
  3582.                 case KEY_DEBUGGED+KEY_H:
  3583. //                  if (!(Game_mode & GM_MULTI) )   {
  3584.                         Players[Player_num].flags ^= PLAYER_FLAGS_CLOAKED;
  3585.                         if (Players[Player_num].flags & PLAYER_FLAGS_CLOAKED) {
  3586.                             #ifdef NETWORK
  3587.                             if (Game_mode & GM_MULTI)
  3588.                                 multi_send_cloak();
  3589.                             #endif
  3590.                             ai_do_cloak_stuff();
  3591.                             Players[Player_num].cloak_time = GameTime;
  3592.                             mprintf((0, "You are cloaked!\n"));
  3593.                         } else
  3594.                             mprintf((0, "You are DE-cloaked!\n"));
  3595. //                  }
  3596.                     break;
  3597.  
  3598.  
  3599.                 case KEY_DEBUGGED+KEY_R:
  3600.                     Robot_firing_enabled = !Robot_firing_enabled;
  3601.                     break;
  3602.  
  3603.                 #ifdef EDITOR       //editor-specific functions
  3604.  
  3605.                     case KEY_E + KEY_DEBUGGED:
  3606.                             network_leave_game();
  3607.                             Function_mode = FMODE_EDITOR; 
  3608.                             break;
  3609.     
  3610.                     case KEY_C + KEY_SHIFTED + KEY_DEBUGGED: 
  3611.                         if (!( Game_mode & GM_MULTI ))
  3612.                             move_player_2_segment(Cursegp,Curside); 
  3613.                         break;   //move eye to curseg
  3614.  
  3615.     
  3616.                     case KEY_DEBUGGED+KEY_W:    draw_world_from_game(); break;
  3617.  
  3618.                 #endif  //#ifdef EDITOR
  3619.     
  3620.                 //flythrough keys
  3621.                 // case KEY_DEBUGGED+KEY_SHIFTED+KEY_F: toggle_flythrough(); break;
  3622.                 // case KEY_LEFT:          ft_preference=FP_LEFT; break;
  3623.                 // case KEY_RIGHT:          ft_preference=FP_RIGHT; break;
  3624.                 // case KEY_UP:            ft_preference=FP_UP; break;
  3625.                 // case KEY_DOWN:          ft_preference=FP_DOWN; break;
  3626.     
  3627.                 case KEY_DEBUGGED+KEY_LAPOSTRO: Show_view_text_timer = 0x30000; object_goto_next_viewer(); break;
  3628.                 case KEY_DEBUGGED+KEY_SHIFTED+KEY_LAPOSTRO: Viewer=ConsoleObject; break;
  3629.     
  3630. #ifndef NDEBUG
  3631.                 case KEY_DEBUGGED+KEY_O: toggle_outline_mode(); break;
  3632. #endif
  3633.                 case KEY_DEBUGGED+KEY_T:
  3634.                     *Toggle_var = !*Toggle_var;
  3635.                     mprintf((0, "Variable at %08x set to %i\n", Toggle_var, *Toggle_var));
  3636.                     break;
  3637.                 case KEY_DEBUGGED + KEY_L: 
  3638.                     if (++Lighting_on >= 2) Lighting_on = 0; break;
  3639.                 case KEY_DEBUGGED + KEY_SHIFTED + KEY_L: 
  3640.                     Beam_brightness=0x38000-Beam_brightness; break;
  3641.                 case KEY_PAD5: slew_stop(); break;
  3642.     
  3643.                 case KEY_DEBUGGED + KEY_F11: play_test_sound(); break;
  3644.                 case KEY_DEBUGGED + KEY_SHIFTED+KEY_F11: advance_sound(); play_test_sound(); break;
  3645.  
  3646.                 case KEY_DEBUGGED +KEY_F4: {
  3647.                     //fvi_info hit_data;
  3648.                     //vms_vector p0 = {-0x1d99a7,-0x1b20000,0x186ab7f};
  3649.                     //vms_vector p1 = {-0x217865,-0x1b20000,0x187de3e};
  3650.                     //find_vector_intersection(&hit_data,&p0,0x1b9,&p1,0x40000,0x0,NULL,-1);
  3651.                     break;
  3652.                 }
  3653.     
  3654.                 case KEY_DEBUGGED + KEY_M:
  3655.                     Debug_spew = !Debug_spew;
  3656.                     if (Debug_spew) {
  3657.                         mopen( 0, 8, 1, 78, 16, "Debug Spew");
  3658.                         HUD_init_message( "Debug Spew: ON" );
  3659.                     } else {
  3660.                         mclose( 0 );
  3661.                         HUD_init_message( "Debug Spew: OFF" );
  3662.                     }
  3663.                     break;      
  3664.     
  3665.                 case KEY_DEBUGGED + KEY_C:  
  3666.  
  3667.                         do_cheat_menu(); 
  3668.                         break;
  3669.                 case KEY_DEBUGGED + KEY_SHIFTED + KEY_A:
  3670.                         do_megawow_powerup(10);
  3671.                         break;
  3672.                 case KEY_DEBUGGED + KEY_A:  {
  3673.                         do_megawow_powerup(200);
  3674. //                      if ( Game_mode & GM_MULTI ) {
  3675. //                          nm_messagebox( NULL, 1, "Damn", "CHEATER!\nYou cannot use the\nmega-thing in network mode." );
  3676. //                          Network_message_reciever = 100;     // Send to everyone...
  3677. //                          sprintf( Network_message, "%s cheated!", Players[Player_num].callsign);
  3678. //                      } else {
  3679. //                          do_megawow_powerup();
  3680. //                      }
  3681.                         break;
  3682.                 }
  3683.     
  3684.                 case KEY_DEBUGGED+KEY_F:    framerate_on = !framerate_on; break;
  3685.     
  3686.                 case KEY_DEBUGGED+KEY_SPACEBAR:              //KEY_F7:                       // Toggle physics flying
  3687.                     slew_stop();
  3688.                     game_flush_inputs();
  3689.                     if ( ConsoleObject->control_type != CT_FLYING ) {
  3690.                         fly_init(ConsoleObject);
  3691.                         Game_suspended &= ~SUSP_ROBOTS;         //robots move
  3692.                     } else {
  3693.                         slew_init(ConsoleObject);                                              //start player slewing
  3694.                         Game_suspended |= SUSP_ROBOTS;          //robots don't move
  3695.                     }
  3696.                     break;
  3697.         
  3698.                 case KEY_DEBUGGED+KEY_COMMA: Render_zoom = fixmul(Render_zoom,62259); break;
  3699.                 case KEY_DEBUGGED+KEY_PERIOD: Render_zoom = fixmul(Render_zoom,68985); break;
  3700.     
  3701.                 case KEY_DEBUGGED+KEY_P+KEY_SHIFTED: Debug_pause = 1; break;
  3702.     
  3703.                 //case KEY_F7: {
  3704.                 //  char mystr[30];
  3705.                 //  sprintf(mystr,"mark %i start",Mark_count);
  3706.                 //  _MARK_(mystr);
  3707.                 //  break;
  3708.                 //}
  3709.                 //case KEY_SHIFTED+KEY_F7: {
  3710.                 //  char mystr[30];
  3711.                 //  sprintf(mystr,"mark %i end",Mark_count);
  3712.                 //  Mark_count++;
  3713.                 //  _MARK_(mystr);
  3714.                 //  break;
  3715.                 //}
  3716.     
  3717.         
  3718. #ifndef NDEBUG
  3719.                 case KEY_DEBUGGED+KEY_F8: speedtest_init(); Speedtest_count = 1;    break;
  3720.                 case KEY_DEBUGGED+KEY_F9: speedtest_init(); Speedtest_count = 10;   break;
  3721.  
  3722.                 case KEY_DEBUGGED+KEY_D:
  3723.                     if ((Game_double_buffer = !Game_double_buffer)!=0)
  3724.                         init_cockpit();
  3725.                     break;
  3726. #endif
  3727.  
  3728. #ifdef EDITOR
  3729.                 case KEY_DEBUGGED+KEY_Q:
  3730.                     stop_time();
  3731.                     dump_used_textures_all();
  3732.                     start_time();
  3733.                     break;
  3734. #endif
  3735.  
  3736.                 #endif      //#ifndef RELEASE
  3737.  
  3738.                 default:        break;
  3739.  
  3740.             }       //switch (key)
  3741.         }
  3742. }
  3743.  
  3744.  
  3745. void vr_reset_display()
  3746. {
  3747.     if (VR_render_mode == VR_NONE ) return;
  3748.  
  3749.     if (VR_screen_mode == SCREEN_MENU)  // low res 320x200 (overall) mode
  3750.         gr_set_mode( SM_320x400U );
  3751.     set_screen_mode (SCREEN_MENU);
  3752.     set_screen_mode (SCREEN_GAME);
  3753. }
  3754.  
  3755.  
  3756. #ifndef NDEBUG
  3757. int Debug_slowdown=0;
  3758. #endif
  3759.  
  3760. #ifdef EDITOR
  3761. extern void player_follow_path(object *objp);
  3762. extern void check_create_player_path(void);
  3763.  
  3764. #endif
  3765.  
  3766. extern  int Do_appearance_effect;
  3767.  
  3768.  
  3769.  
  3770. void GameLoop(int RenderFlag, int ReadControlsFlag )
  3771. {
  3772.     static int desc_dead_countdown=100;   /*  used if player shouldn't be playing */
  3773.  
  3774. #ifndef NDEBUG
  3775.     //  Used to slow down frame rate for testing things.
  3776. //  RenderFlag = 1; // DEBUG
  3777.     if (Debug_slowdown) {
  3778.         int h, i, j=0;
  3779.  
  3780.         for (h=0; h<Debug_slowdown; h++)
  3781.             for (i=0; i<1000; i++)
  3782.                 j += i;
  3783.     }
  3784. #endif
  3785.  
  3786.         if (desc_id_exit_num) {              // are we supposed to be checking
  3787.             if (!(--desc_dead_countdown))  // if so, at zero, then pull the plug
  3788.                 Error ("Loading overlay -- error number: %d\n", (int)desc_id_exit_num);
  3789.         }
  3790.                 
  3791.         #ifndef RELEASE
  3792.         if (FindArg("-invulnerability"))
  3793.             Players[Player_num].flags |= PLAYER_FLAGS_INVULNERABLE;
  3794.         #endif
  3795.  
  3796.         update_player_stats();
  3797.         diminish_palette_towards_normal();      //  Should leave palette effect up for as long as possible by putting right before render.
  3798.         //--killed--do_afterburner_stuff();
  3799.         do_cloak_stuff();
  3800.         do_invulnerable_stuff();
  3801.         remove_obsolete_stuck_objects();
  3802. #ifdef EDITOR
  3803. check_create_player_path();
  3804. player_follow_path(ConsoleObject);
  3805. #endif
  3806.         #ifdef NETWORK
  3807.         if (Game_mode & GM_MULTI)
  3808.             multi_do_frame();
  3809.         #endif
  3810.  
  3811.         if (RenderFlag) {
  3812.             if (force_cockpit_redraw) {         //screen need redrawing?
  3813.                 init_cockpit();
  3814.                 force_cockpit_redraw=0;
  3815.             }
  3816.             game_render_frame();
  3817.         }
  3818.  
  3819. //      mprintf(0,"Velocity %2.2f\n", f2fl(vm_vec_mag(&ConsoleObject->phys_info.velocity)));
  3820.  
  3821. #if 0
  3822. mem_fill();
  3823. mem_check();
  3824. #endif
  3825.  
  3826.         calc_frame_time();
  3827.  
  3828.         dead_player_frame();
  3829.         if (Newdemo_state != ND_STATE_PLAYBACK)
  3830.             do_controlcen_dead_frame();
  3831.  
  3832.         if (ReadControlsFlag)
  3833.             ReadControls();
  3834.         else
  3835.             memset(&Controls, 0, sizeof(Controls));
  3836.  
  3837.         GameTime += FrameTime;
  3838.  
  3839.         digi_sync_sounds();
  3840.  
  3841.         if (Endlevel_sequence) {
  3842.             do_endlevel_frame();
  3843.             powerup_grab_cheat_all();
  3844.             do_special_effects();
  3845.             return;                 //skip everything else
  3846.         }
  3847.  
  3848.         #ifdef ARCADE
  3849.         if (Arcade_mode && (Arcade_timer<0) && (Newdemo_state != ND_STATE_PLAYBACK) )   {
  3850.             memset( &Controls, 0, sizeof(Controls) );
  3851.             continue;
  3852.         }
  3853.         #endif
  3854.  
  3855.         if (Newdemo_state != ND_STATE_PLAYBACK)
  3856.             do_exploding_wall_frame();
  3857.         if ((Newdemo_state != ND_STATE_PLAYBACK) || (Newdemo_vcr_state != ND_STATE_PAUSED)) {
  3858.             do_special_effects();
  3859.             wall_frame_process();
  3860.             triggers_frame_process();
  3861.         }
  3862.  
  3863.  
  3864.         if (Fuelcen_control_center_destroyed)   {
  3865.             if (Newdemo_state==ND_STATE_RECORDING )
  3866.                 newdemo_record_control_center_destroyed();
  3867.             flash_frame();
  3868.         }
  3869.         
  3870.         if ( Newdemo_state == ND_STATE_PLAYBACK )   {
  3871.             newdemo_playback_one_frame();
  3872.             if ( Newdemo_state != ND_STATE_PLAYBACK )       {
  3873.                 longjmp( LeaveGame, 0 );        // Go back to menu
  3874.             }
  3875.         } else  
  3876.         { // Note the link to above!
  3877.  
  3878.             Players[Player_num].homing_object_dist = -1;        //  Assume not being tracked.  Laser_do_weapon_sequence modifies this.
  3879.  
  3880.             object_move_all();  
  3881.             powerup_grab_cheat_all();
  3882.  
  3883.             if (Endlevel_sequence)  //might have been started during move
  3884.                 return;
  3885.  
  3886.             fuelcen_update_all();
  3887.  
  3888.             do_ai_frame_all();
  3889.  
  3890.             if (allowed_to_fire_laser()) {
  3891.                 Global_laser_firing_count += Weapon_info[Primary_weapon_to_weapon_info[Primary_weapon]].fire_count * (Controls.fire_primary_state || Controls.fire_primary_down_count);
  3892.                 if ((Primary_weapon == FUSION_INDEX) && (Global_laser_firing_count)) {
  3893.                     if ((Players[Player_num].energy < F1_0*2) && (Auto_fire_fusion_cannon_time == 0)) {
  3894.                         Global_laser_firing_count = 0;
  3895.                     } else {
  3896.                         if (Fusion_charge == 0)
  3897.                             Players[Player_num].energy -= F1_0*2;
  3898.  
  3899.                         Fusion_charge += FrameTime;
  3900.                         Players[Player_num].energy -= FrameTime;
  3901.  
  3902.                         if (Players[Player_num].energy <= 0) {
  3903.                             Players[Player_num].energy = 0;
  3904.                             Auto_fire_fusion_cannon_time = GameTime -1;             //  Fire now!
  3905.                         } else
  3906.                             Auto_fire_fusion_cannon_time = GameTime + FrameTime/2 + 1;      //  Fire the fusion cannon at this time in the future.
  3907.  
  3908.                         if (Fusion_charge < F1_0*2) {
  3909.                             PALETTE_FLASH_ADD(Fusion_charge >> 11, 0, Fusion_charge >> 11);
  3910.                         } else {
  3911.                             PALETTE_FLASH_ADD(Fusion_charge >> 11, Fusion_charge >> 11, 0);
  3912.                         }
  3913.  
  3914.                         if (Fusion_next_sound_time < GameTime) {
  3915.                             if (Fusion_charge > F1_0*2) {
  3916.                                 digi_play_sample( 11, F1_0 );
  3917.                                 apply_damage_to_player(ConsoleObject, ConsoleObject, rand() * 4);
  3918.                             } else {
  3919.                                 create_awareness_event(ConsoleObject, PA_WEAPON_ROBOT_COLLISION);
  3920.                                 digi_play_sample( SOUND_FUSION_WARMUP, F1_0 );
  3921.                                 #ifdef NETWORK
  3922.                                 if (Game_mode & GM_MULTI)
  3923.                                     multi_send_play_sound(SOUND_FUSION_WARMUP, F1_0);
  3924.                                 #endif
  3925.                             }
  3926.                             Fusion_next_sound_time = GameTime + F1_0/8 + rand()/4;
  3927.                         }
  3928.                     }
  3929.                 }
  3930.             }
  3931.  
  3932.             if (Auto_fire_fusion_cannon_time) {
  3933.                 if (Primary_weapon != FUSION_INDEX)
  3934.                     Auto_fire_fusion_cannon_time = 0;
  3935.                 else if (GameTime + FrameTime/2 >= Auto_fire_fusion_cannon_time) {
  3936.                     Auto_fire_fusion_cannon_time = 0;
  3937.                     Global_laser_firing_count = 1;
  3938.                 } else {
  3939.                     vms_vector  rand_vec;
  3940.                     fix         bump_amount;
  3941.  
  3942.                     Global_laser_firing_count = 0;
  3943.  
  3944.                     ConsoleObject->mtype.phys_info.rotvel.x += (rand() - 16384)/8;
  3945.                     ConsoleObject->mtype.phys_info.rotvel.z += (rand() - 16384)/8;
  3946.                     make_random_vector(&rand_vec);
  3947.  
  3948.                     bump_amount = F1_0*4;
  3949.  
  3950.                     if (Fusion_charge > F1_0*2)
  3951.                         bump_amount = Fusion_charge*4;
  3952.  
  3953.                     bump_one_object(ConsoleObject, &rand_vec, bump_amount);
  3954.                 }
  3955.             }
  3956.  
  3957.             if (Global_laser_firing_count) {
  3958.                 //  Don't cap here, gets capped in Laser_create_new and is based on whether in multiplayer mode, MK, 3/27/95
  3959.                 // if (Fusion_charge > F1_0*2)
  3960.                 //  Fusion_charge = F1_0*2;
  3961.                 Global_laser_firing_count -= do_laser_firing_player();  //do_laser_firing(Players[Player_num].objnum, Primary_weapon);
  3962.             }
  3963.  
  3964.             if (Global_laser_firing_count < 0)
  3965.                 Global_laser_firing_count = 0;
  3966.         }
  3967.  
  3968.     if (Do_appearance_effect) {
  3969.         create_player_appearance_effect(ConsoleObject);
  3970.         Do_appearance_effect = 0;
  3971.     }
  3972. }
  3973.  
  3974. //  -------------------------------------------------------------------------------------------------------
  3975. //  If player is close enough to objnum, which ought to be a powerup, pick it up!
  3976. //  This could easily be made difficulty level dependent.
  3977. void powerup_grab_cheat(object *player, int objnum)
  3978. {
  3979.     fix powerup_size;
  3980.     fix player_size;
  3981.     fix dist;
  3982.  
  3983.     Assert(Objects[objnum].type == OBJ_POWERUP);
  3984.  
  3985.     powerup_size = Objects[objnum].size;
  3986.     player_size = player->size;
  3987.  
  3988.     dist = vm_vec_dist_quick(&Objects[objnum].pos, &player->pos);
  3989.  
  3990.     if ((dist < 2*(powerup_size + player_size)) && !(Objects[objnum].flags & OF_SHOULD_BE_DEAD)) {
  3991.         vms_vector  collision_point;
  3992.  
  3993.         vm_vec_avg(&collision_point, &Objects[objnum].pos, &player->pos);
  3994.         collide_player_and_powerup(player, &Objects[objnum], &collision_point);
  3995.     }
  3996. }
  3997.  
  3998. //  -------------------------------------------------------------------------------------------------------
  3999. //  Make it easier to pick up powerups.
  4000. //  For all powerups in this segment, pick them up at up to twice pickuppable distance based on dot product
  4001. //  from player to powerup and player's forward vector.
  4002. //  This has the effect of picking them up more easily left/right and up/down, but not making them disappear
  4003. //  way before the player gets there.
  4004. void powerup_grab_cheat_all(void)
  4005. {
  4006.     segment *segp;
  4007.     int     objnum;
  4008.  
  4009.     segp = &Segments[ConsoleObject->segnum];
  4010.     objnum = segp->objects;
  4011.  
  4012.     while (objnum != -1) {
  4013.         if (Objects[objnum].type == OBJ_POWERUP)
  4014.             powerup_grab_cheat(ConsoleObject, objnum);
  4015.         objnum = Objects[objnum].next;
  4016.     }
  4017.  
  4018. }
  4019.  
  4020. int Last_level_path_created = -1;
  4021.  
  4022. #ifdef SHOW_EXIT_PATH
  4023.  
  4024. //  ------------------------------------------------------------------------------------------------------------------
  4025. //  Create path for player from current segment to goal segment.
  4026. //  Return true if path created, else return false.
  4027. int mark_player_path_to_segment(int segnum)
  4028. {
  4029.     int     i;
  4030.     object  *objp = ConsoleObject;
  4031.     short       player_path_length=0;
  4032.     int     player_hide_index=-1;
  4033.  
  4034.     if (Last_level_path_created == Current_level_num) {
  4035.         return 0;
  4036.     }
  4037.  
  4038.     Last_level_path_created = Current_level_num;
  4039.  
  4040.     if (create_path_points(objp, objp->segnum, segnum, Point_segs_free_ptr, &player_path_length, 100, 0, 0, -1) == -1) {
  4041.         mprintf((0, "Unable to form path of length %i for myself\n", 100));
  4042.         return 0;
  4043.     }
  4044.  
  4045.     player_hide_index = Point_segs_free_ptr - Point_segs;
  4046.     Point_segs_free_ptr += player_path_length;
  4047.  
  4048.     if (Point_segs_free_ptr - Point_segs + MAX_PATH_LENGTH*2 > MAX_POINT_SEGS) {
  4049.         mprintf((1, "Can't create path.  Not enough point_segs.\n"));
  4050.         ai_reset_all_paths();
  4051.         return 0;
  4052.     }
  4053.  
  4054.     for (i=1; i<player_path_length; i++) {
  4055.         int         segnum, objnum;
  4056.         vms_vector  seg_center;
  4057.         object      *obj;
  4058.  
  4059.         segnum = Point_segs[player_hide_index+i].segnum;
  4060.         mprintf((0, "%3i ", segnum));
  4061.         seg_center = Point_segs[player_hide_index+i].point;
  4062.  
  4063.         objnum = obj_create( OBJ_POWERUP, POW_ENERGY, segnum, &seg_center, &vmd_identity_matrix, Powerup_info[POW_ENERGY].size, CT_POWERUP, MT_NONE, RT_POWERUP);
  4064.         if (objnum == -1) {
  4065.             Int3();     //  Unable to drop energy powerup for path
  4066.             return 1;
  4067.         }
  4068.  
  4069.         obj = &Objects[objnum];
  4070.         obj->rtype.vclip_info.vclip_num = Powerup_info[obj->id].vclip_num;
  4071.         obj->rtype.vclip_info.frametime = Vclip[obj->rtype.vclip_info.vclip_num].frame_time;
  4072.         obj->rtype.vclip_info.framenum = 0;
  4073.         obj->lifeleft = F1_0*100 + rand() * 4;
  4074.     }
  4075.  
  4076.     mprintf((0, "\n"));
  4077.     return 1;
  4078. }
  4079.  
  4080. //  Return true if it happened, else return false.
  4081. int create_special_path(void)
  4082. {
  4083.     int i,j;
  4084.  
  4085.     //  ---------- Find exit doors ----------
  4086.     for (i=0; i<=Highest_segment_index; i++)
  4087.         for (j=0; j<MAX_SIDES_PER_SEGMENT; j++)
  4088.             if (Segments[i].children[j] == -2) {
  4089.                 mprintf((0, "Exit at segment %i\n", i));
  4090.                 return mark_player_path_to_segment(i);
  4091.             }
  4092.  
  4093.     return 0;
  4094. }
  4095.  
  4096. #endif
  4097.  
  4098.  
  4099. #ifndef RELEASE
  4100. int Max_obj_count_mike = 0;
  4101.  
  4102. //  Shows current number of used objects.
  4103. void show_free_objects(void)
  4104. {
  4105.     if (!(FrameCount & 8)) {
  4106.         int i;
  4107.         int count=0;
  4108.  
  4109.         mprintf((0, "Highest_object_index = %3i, MAX_OBJECTS = %3i, now used = ", Highest_object_index, MAX_OBJECTS));
  4110.  
  4111.         for (i=0; i<=Highest_object_index; i++)
  4112.             if (Objects[i].type != OBJ_NONE)
  4113.                 count++;
  4114.  
  4115.         mprintf((0, "%3i", count));
  4116.  
  4117.         if (count > Max_obj_count_mike) {
  4118.             Max_obj_count_mike = count;
  4119.             mprintf((0, " ***"));
  4120.         }
  4121.  
  4122.         mprintf((0, "\n"));
  4123.     }
  4124.  
  4125. }
  4126.  
  4127. #define FILL_VAL    0xcc        //  int 3 opcode value
  4128.  
  4129.  
  4130. extern void code_01s(void), code_01e(void);
  4131. extern void code_02s(void), code_02e(void);
  4132. extern void code_03s(void), code_03e(void);
  4133. extern void code_04s(void), code_04e(void);
  4134. extern void code_05s(void), code_05e(void);
  4135. extern void code_06s(void), code_06e(void);
  4136. extern void code_07s(void), code_07e(void);
  4137. extern void code_08s(void), code_08e(void);
  4138. extern void code_09s(void), code_09e(void);
  4139. extern void code_10s(void), code_10e(void);
  4140. extern void code_11s(void), code_11e(void);
  4141. extern void code_12s(void), code_12e(void);
  4142. extern void code_13s(void), code_13e(void);
  4143. extern void code_14s(void), code_14e(void);
  4144. extern void code_15s(void), code_15e(void);
  4145. extern void code_16s(void), code_16e(void);
  4146. extern void code_17s(void), code_17e(void);
  4147. extern void code_18s(void), code_18e(void);
  4148. extern void code_19s(void), code_19e(void);
  4149. extern void code_20s(void), code_20e(void);
  4150. extern void code_21s(void), code_21e(void);
  4151.  
  4152. int Mem_filled = 0;
  4153.  
  4154. void fill_func(char *start, char *end, char value)
  4155. {
  4156.     char    *i;
  4157.  
  4158.     mprintf((0, "Filling from %8x to %8x\n", start, end));
  4159.  
  4160.     for (i=start; i<end; i++)
  4161.         *i = value;
  4162.  
  4163. }
  4164.  
  4165. void check_func(char *start, char *end, char value)
  4166. {
  4167.     char    *i;
  4168.  
  4169.     for (i=start; i<end; i++)
  4170.         if (*i != value) {
  4171.             Int3();     //  The nast triple aught six bug...we can smell it...contact Mike!
  4172.             Error("Oops, the nasty triple aught six bug.  Address == %8x\n", i);
  4173.         }
  4174.  
  4175. }
  4176.  
  4177. #if 0
  4178. void mem_fill(void)
  4179. {
  4180.     if (Mem_filled)
  4181.         return;
  4182.  
  4183.     Mem_filled = 1;
  4184.  
  4185.     fill_func((char *) code_01s, (char *) code_01e, FILL_VAL);
  4186.     fill_func((char *) code_02s, (char *) code_02e, FILL_VAL);
  4187.     fill_func((char *) code_03s, (char *) code_03e, FILL_VAL);
  4188.     fill_func((char *) code_04s, (char *) code_04e, FILL_VAL);
  4189.     fill_func((char *) code_05s, (char *) code_05e, FILL_VAL);
  4190.     fill_func((char *) code_06s, (char *) code_06e, FILL_VAL);
  4191.     fill_func((char *) code_07s, (char *) code_07e, FILL_VAL);
  4192.     fill_func((char *) code_08s, (char *) code_08e, FILL_VAL);
  4193.     fill_func((char *) code_09s, (char *) code_09e, FILL_VAL);
  4194.     fill_func((char *) code_10s, (char *) code_10e, FILL_VAL);
  4195.     fill_func((char *) code_11s, (char *) code_11e, FILL_VAL);
  4196.     fill_func((char *) code_12s, (char *) code_12e, FILL_VAL);
  4197.     fill_func((char *) code_13s, (char *) code_13e, FILL_VAL);
  4198.     fill_func((char *) code_14s, (char *) code_14e, FILL_VAL);
  4199.     fill_func((char *) code_15s, (char *) code_15e, FILL_VAL);
  4200.     fill_func((char *) code_16s, (char *) code_16e, FILL_VAL);
  4201.     fill_func((char *) code_17s, (char *) code_17e, FILL_VAL);
  4202.     fill_func((char *) code_18s, (char *) code_18e, FILL_VAL);
  4203.     fill_func((char *) code_19s, (char *) code_19e, FILL_VAL);
  4204.     fill_func((char *) code_20s, (char *) code_20e, FILL_VAL);
  4205.     fill_func((char *) code_21s, (char *) code_21e, FILL_VAL);
  4206. }
  4207.  
  4208. void mem_check(void)
  4209. {
  4210.     check_func((char *) code_01s, (char *) code_01e, FILL_VAL);
  4211.     check_func((char *) code_02s, (char *) code_02e, FILL_VAL);
  4212.     check_func((char *) code_03s, (char *) code_03e, FILL_VAL);
  4213.     check_func((char *) code_04s, (char *) code_04e, FILL_VAL);
  4214.     check_func((char *) code_05s, (char *) code_05e, FILL_VAL);
  4215.     check_func((char *) code_06s, (char *) code_06e, FILL_VAL);
  4216.     check_func((char *) code_07s, (char *) code_07e, FILL_VAL);
  4217.     check_func((char *) code_08s, (char *) code_08e, FILL_VAL);
  4218.     check_func((char *) code_09s, (char *) code_09e, FILL_VAL);
  4219.     check_func((char *) code_10s, (char *) code_10e, FILL_VAL);
  4220.     check_func((char *) code_11s, (char *) code_11e, FILL_VAL);
  4221.     check_func((char *) code_12s, (char *) code_12e, FILL_VAL);
  4222.     check_func((char *) code_13s, (char *) code_13e, FILL_VAL);
  4223.     check_func((char *) code_14s, (char *) code_14e, FILL_VAL);
  4224.     check_func((char *) code_15s, (char *) code_15e, FILL_VAL);
  4225.     check_func((char *) code_16s, (char *) code_16e, FILL_VAL);
  4226.     check_func((char *) code_17s, (char *) code_17e, FILL_VAL);
  4227.     check_func((char *) code_18s, (char *) code_18e, FILL_VAL);
  4228.     check_func((char *) code_19s, (char *) code_19e, FILL_VAL);
  4229.     check_func((char *) code_20s, (char *) code_20e, FILL_VAL);
  4230.     check_func((char *) code_21s, (char *) code_21e, FILL_VAL);
  4231. }
  4232. #endif
  4233. #endif
  4234.